[java] Jackson은 ‘is’를 제거하여 기본 부울 필드의 이름을 바꿉니다.

중복 일 수 있습니다. 그러나 내 문제에 대한 해결책을 찾을 수 없습니다.

나는 수업이있다

public class MyResponse implements Serializable {

    private boolean isSuccess;

    public boolean isSuccess() {
        return isSuccess;
    }

    public void setSuccess(boolean isSuccess) {
        this.isSuccess = isSuccess;
    }
}

Getter 및 Setter는 Eclipse에서 생성됩니다.

다른 클래스에서 값을 true로 설정하고 JSON 문자열로 씁니다.

System.out.println(new ObjectMapper().writeValueAsString(myResponse));

JSON에서 키는 {"success": true}.

isSuccess자체를 원합니다 . 직렬화 중에 Jackson이 setter 메서드를 사용하고 있습니까? 키를 필드 이름 자체로 만드는 방법은 무엇입니까?



답변

이것은 약간 늦은 답변이지만이 페이지를 방문하는 다른 사람에게 유용 할 수 있습니다.

Jackson이 JSON으로 직렬화 할 때 사용할 이름을 변경하는 간단한 해결책은 @JsonProperty 주석 을 사용하는 것이므로 예제는 다음과 같습니다.

public class MyResponse implements Serializable {

    private boolean isSuccess;

    @JsonProperty(value="isSuccess")
    public boolean isSuccess() {
        return isSuccess;
    }

    public void setSuccess(boolean isSuccess) {
        this.isSuccess = isSuccess;
    }
}

그런 다음 JSON으로 직렬화 {"isSuccess":true}되지만 getter 메서드 이름을 수정할 필요가 없다는 이점이 있습니다.

이 경우 @JsonProperty("isSuccess")단일 value요소 만 있으므로 주석을 작성할 수도 있습니다.


답변

나는 최근 에이 문제를 만났고 이것이 내가 찾은 것입니다. Jackson은 getter 및 setter에 대해 전달하는 모든 클래스를 검사하고 직렬화 및 역 직렬화에 해당 메서드를 사용합니다. 이러한 메소드에서 “get”, “is”및 “set”뒤에 오는 것은 JSON 필드의 키로 사용됩니다 (getIsValid 및 setIsValid의 경우 “isValid”).

public class JacksonExample {

    private boolean isValid = false;

    public boolean getIsValid() {
        return isValid;
    }

    public void setIsValid(boolean isValid) {
        this.isValid = isValid;
    }
}

유사하게 “isSuccess”는 “isIsSuccess”또는 “getIsSuccess”로 이름이 변경되지 않는 한 “success”가됩니다.

여기에서 더 읽기 : http://www.citrine.io/blog/2015/5/20/jackson-json-processor


답변

아래의 두 주석을 모두 사용하면 출력 JSON에 다음이 포함됩니다 is_xxx.

@get:JsonProperty("is_something")
@param:JsonProperty("is_something")


답변

ObjectMapper다음과 같이 구성 할 수 있습니다 .

mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
            @Override
            public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
            {
                if(method.hasReturnType() && (method.getRawReturnType() == Boolean.class || method.getRawReturnType() == boolean.class)
                        && method.getName().startsWith("is")) {
                    return method.getName();
                }
                return super.nameForGetterMethod(config, method, defaultName);
            }
        });


답변

Kotlin 및 데이터 클래스를 사용하는 경우 :

data class Dto(
    @get:JsonProperty("isSuccess") val isSuccess: Boolean
)

@param:JsonProperty("isSuccess")JSON도 역 직렬화 하려는 경우 추가해야 할 수 있습니다 .


답변

Utkarsh의 대답을 기반으로 구축 ..

get / is를 제외한 Getter 이름 이 JSON 이름으로 사용됩니다.

public class Example{
    private String radcliffe;

    public getHarryPotter(){
        return radcliffe;
    }
}

{ “harryPotter”: “whateverYouGaveHere”} 로 저장됩니다 .


Deserialization의 경우 Jackson은 setter와 필드 이름을 모두 확인합니다. Json String { “word1”: “example”}의 경우 아래 두 가지 모두 유효합니다.

public class Example{
    private String word1;

    public setword2( String pqr){
        this.word1 = pqr;
    }
}

public class Example2{
    private String word2;

    public setWord1(String pqr){
        this.word2 = pqr ;
    }
}

더 흥미로운 질문은 Jackson이 deserialization을 위해 고려하는 순서입니다. { “word1”: “myName”}을 다음같이 deserialize하려고하면

public class Example3{
    private String word1;
    private String word2;

    public setWord1( String parameter){
        this.word2 = parameter ;
    }
}

위의 경우를 테스트하지는 않았지만 word1 & word2 의 값을 보는 것은 흥미로울 것입니다 .

참고 : 어떤 필드가 동일해야하는지 강조하기 위해 완전히 다른 이름을 사용했습니다.


답변

이 문제에 대한 또 다른 방법이 있습니다.

새 하위 클래스를 정의하면 PropertyNamingStrategy가 확장되고 ObjectMapper 인스턴스에 전달됩니다.

다음은 더 많은 도움이 될 수있는 코드 스 니펫입니다.

mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
        @Override
        public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
            String input = defaultName;
            if(method.getName().startsWith("is")){
                input = method.getName();
            }

            //copy from LowerCaseWithUnderscoresStrategy
            if (input == null) return input; // garbage in, garbage out
            int length = input.length();
            StringBuilder result = new StringBuilder(length * 2);
            int resultLength = 0;
            boolean wasPrevTranslated = false;
            for (int i = 0; i < length; i++)
            {
                char c = input.charAt(i);
                if (i > 0 || c != '_') // skip first starting underscore
                {
                    if (Character.isUpperCase(c))
                    {
                        if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_')
                        {
                            result.append('_');
                            resultLength++;
                        }
                        c = Character.toLowerCase(c);
                        wasPrevTranslated = true;
                    }
                    else
                    {
                        wasPrevTranslated = false;
                    }
                    result.append(c);
                    resultLength++;
                }
            }
            return resultLength > 0 ? result.toString() : input;
        }
    });