복붙노트

[SPRING] 선두의 낙타 름 단어가 한 글자 밖에없는 경우 왜 Jackson 2는 첫 번째 대문자를 인식하지 못합니까?

SPRING

선두의 낙타 름 단어가 한 글자 밖에없는 경우 왜 Jackson 2는 첫 번째 대문자를 인식하지 못합니까?

스프링 4 MVC를 Jackson 2와 함께 사용하고 있습니다. 하나의 작업에 대해 속성이있는 요청 개체가 있는데, 이는 앞의 낙타의 경우 단어가 길이가 한 문자 인 경우입니다.

private String aLogId;

이 클래스에는 적절히 명명 된 getter와 setter가 있습니다.

public String getALogId() { return aLogId; }
public void setALogId(String aLogId) { this.aLogId = aLogId; }

그러나 해당 JSON 속성을 사용하여이 서비스에 대한 요청을 게시하려고 할 때 :

{"aLogId":"This is a log id"}

필드가 인식되지 않고 컨트롤러 클래스가 호출되지 않는다고 말하는 Spring 프레임 워크에서 500 응답을 받았습니다.

그러나 "L"을 소문자로 변경하면 요청이 예상대로 비 직렬화되고 내 컨트롤러 클래스가 히트됩니다.

{"alogId":"This is a log id"}

왜 Jackson은 속성에 대한 낙타 사례 협약에서 두 번째 단어가 분명하고 대문자로 표시 될 때 "L"을 소문자로 간주합니까? 첫 단어가 한 글자 밖에 없기 때문입니까?

첫 번째 단어가 두 개 이상의 글자이고 다른 단어의 속성이 일치하지 않으면이 동일한 문제가 발생하지 않는 요청 개체의 다른 특성이 있습니다.

해결법

  1. ==============================

    1.여러분이보고있는 문제는 Jackson이 Java Bean 명명 규칙을 사용하여 Java 클래스의 Json 속성을 파악하기 때문입니다.

    여러분이보고있는 문제는 Jackson이 Java Bean 명명 규칙을 사용하여 Java 클래스의 Json 속성을 파악하기 때문입니다.

    다음은 보이는 특정 문제에 대한 참고 자료입니다. 귀하의 분야에서 처음 두 글자를 대문자로 사용하지 않는 것이 좋습니다. IntelliJ 또는 Eclipse와 같은 IDE를 사용하고 IDE가 사용자 대신 setter를 생성하게하면 동일한 "동작"이 발생하므로 다음과 같은 방법으로 끝납니다.

    public void setaLogId(String aLogId) {
        this.aLogId = aLogId;
    }
    
    public String getaLogId() {
        return aLogId;
    }
    

    따라서 "L"을 소문자로 변경하면 Jackson은 매핑하려는 필드를 알아낼 수있었습니다.

    위에서 말했듯이 "aLogId"필드 이름을 사용하고 Jackson 작업을 수행하려면 @Logind가있는 @JsonProperty 주석을 사용하는 것뿐입니다.

    @JsonProperty("aLogId")
    private String aLogId;
    

    다음 테스트 코드는 이것이 어떻게 작동하는지 보여줍니다.

    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class Test {
    
        @JsonProperty("aLogId")
        private String aLogId;
    
        public void setaLogId(String aLogId) {
            this.aLogId = aLogId;
        }
    
        public String getaLogId() {
            return aLogId;
        }
    
        public static void main(String[] args) {
    
            ObjectMapper objectMapper = new ObjectMapper();
    
            Test test = new Test();
    
            test.setaLogId("anId");
    
            try {
                System.out.println("Serialization test: " + objectMapper.writeValueAsString(test));
    
    
                String json = "{\"aLogId\":\"anotherId\"}";
    
                Test anotherTest = objectMapper.readValue(json, Test.class);
    
                System.out.println("Deserialization test: " +anotherTest.getaLogId());
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }
    

    테스트 결과는 다음과 같습니다.

    직렬화 테스트 : { "aLogId": "anId"}

    직렬화 복원 테스트 : anotherId

  2. ==============================

    2.나의 이해는 Jackson이 기본적으로 자체 명명 규칙을 사용한다는 것인데, 이는 Java Bean 명명 규칙에 매우 가깝지만 똑같은 것은 아닙니다. MapperFeature 옵션 인 MapperFeature.USE_STD_BEAN_NAMING이 Jackson 2.5.0에 추가되어 Jackson에게 Java Bean 명명 규칙을 사용하도록 지시합니다 (Jackson Issue 653 참조). 이전 버전과의 호환성을 위해 MapperFeature.USE_STD_BEAN_NAMING의 기본값은 false입니다.

    나의 이해는 Jackson이 기본적으로 자체 명명 규칙을 사용한다는 것인데, 이는 Java Bean 명명 규칙에 매우 가깝지만 똑같은 것은 아닙니다. MapperFeature 옵션 인 MapperFeature.USE_STD_BEAN_NAMING이 Jackson 2.5.0에 추가되어 Jackson에게 Java Bean 명명 규칙을 사용하도록 지시합니다 (Jackson Issue 653 참조). 이전 버전과의 호환성을 위해 MapperFeature.USE_STD_BEAN_NAMING의 기본값은 false입니다.

  3. ==============================

    3.이것은 나를 위해 일했다. getters에 대한 @JsonProperty 주석!

    이것은 나를 위해 일했다. getters에 대한 @JsonProperty 주석!

    import com.fasterxml.jackson.annotation.JsonProperty;
    
    public class PaytmRequestJson {
        private String ORDERID;
        private String MID;
        private String CHECKSUMHASH;
    
        @JsonProperty("ORDERID")
        public String getORDERID() {
            return ORDERID;
        }
    
        public void setORDERID(String ORDERID) {
            this.ORDERID = ORDERID;
        }
    
        @JsonProperty("MID")
        public String getMID() {
            return MID;
        }
    
        public void setMID(String MID) {
            this.MID = MID;
        }
    
        @JsonProperty("CHECKSUMHASH")
        public String getCHECKSUMHASH() {
            return CHECKSUMHASH;
        }
    
        public void setCHECKSUMHASH(String CHECKSUMHASH) {
            this.CHECKSUMHASH = CHECKSUMHASH;
        }
    }
    
  4. ==============================

    4.@JsonProperty는 현재 답변에서 제안한대로 단 하나의 속성마다 반복해야한다는 단점이 있으며 침입적임 (매핑되는 클래스를 변경해야 함)이라는 단점이 있습니다.

    @JsonProperty는 현재 답변에서 제안한대로 단 하나의 속성마다 반복해야한다는 단점이 있으며 침입적임 (매핑되는 클래스를 변경해야 함)이라는 단점이 있습니다.

    보다 일반적인 접근법은 사용자 정의 속성 명명 전략을 제공하는 것입니다.

    자바:

    public class CobraCaseX extends PropertyNamingStrategy.PropertyNamingStrategyBase {
        private static final Pattern REGEX = Pattern.compile("[A-Z]");
    
        @Override
        public String translate(String input) {
            if (input == null)
                return input; // garbage in, garbage out
    
            if (!input.isEmpty() && Character.isUpperCase(input.charAt(0)))
                input = input.substring(0, 1).toLowerCase() + input.substring(1);
    
            return REGEX.matcher(input).replaceAll("_$0").toLowerCase();
        }
    }
    

    코 틀린 :

    class CustomSnakeCase : PropertyNamingStrategy.PropertyNamingStrategyBase() {
        private companion object {
            val REGEX = Regex("[A-Z]")
        }
    
        override fun translate(input: String?) =
            input?.decapitalize()?.replace(REGEX, "_$0")?.toLowerCase()
    }
    

    용법:

    new ObjectMapper()
        .setPropertyNamingStrategy(new CustomSnakeCase())
        .enable(MapperFeature.USE_STD_BEAN_NAMING)
    

    노트 : 위의 구현은 입력이 camelCase (대문자 시작 없음)라고 가정합니다. aField와 같은 1 문자 접두어를 일관되게 처리하려면 USE_STD_BEAN_NAMING이 필요합니다.

    구현시 다음 매핑을 제공하므로 필요에 따라 조정할 수 있습니다.

    camelCase      snake_case
    ----------------------------
    simple         simple
    a              a
    sepaRated      sepa_rated
    iOException    i_o_exception
    xOffset        x_offset
    theWWW         the_w_w_w
    sepaRated32    sepa_rated32
    sepa32Rated    sepa32_rated
    
  5. from https://stackoverflow.com/questions/30205006/why-does-jackson-2-not-recognize-the-first-capital-letter-if-the-leading-camel-c by cc-by-sa and MIT license