it-source

Jackson은 'is'를 제거하여 기본 부울 필드의 이름을 바꿉니다.

criticalcode 2023. 2. 8. 17:59
반응형

Jackson은 'is'를 제거하여 기본 부울 필드의 이름을 바꿉니다.

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

수업이 있다

public class MyResponse implements Serializable {

    private boolean isSuccess;

    public boolean isSuccess() {
        return isSuccess;
    }

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

Getters 및 setters는 Eclipse에 의해 생성됩니다.

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

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

가 JSON으로 .{"success": true}.

는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.isSuccess그 자체입니다.Jackson'setter?키를 필드 이름 자체로 만들려면 어떻게 해야 합니까?

다소 늦은 답변이지만 이 페이지에 접속하는 다른 사용자에게 도움이 될 수 있습니다.

잭슨이 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}, 이름을

에는 ''을 ''으로 쓸 수도 .@JsonProperty("isSuccess")밖에 value에 의존하다

나는 최근에 이 문제에 부딪혔는데 이것이 내가 발견한 것이다.Jackson은 getters와 setters에 전달된 모든 클래스를 검사하고 이러한 메서드를 사용하여 직렬화 및 직렬화를 해제합니다.이러한 메서드에서 "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" 또는 "getIsSuccess"로 이름을 바꾸지 않는 한 "isSuccess"는 "성공"이 됩니다.

자세한 내용은 이쪽:http://www.citrine.io/blog/2015/5/20/jackson-json-processor

두 로 JSON이 되도록 합니다.is_xxx:

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

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

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

하면 '어울리지 않다'를 할 도 있어요.@param:JsonProperty("isSuccess")JSON을 사용하다

문서를 하는 경우 은 ":"로 됩니다.readOnly「」를 하고 있는 @get:JsonProperty문제를 과 같이하면

@JsonAutoDetect(isGetterVisibility = JsonAutoDetect.Visibility.NONE)
data class Dto(
    @field:JsonProperty(value = "isSuccess") val isSuccess: Boolean
)

설정할 수 .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);
            }
        });

커스텀 네이밍 전략을 조작하거나 접근자를 재작성하고 싶지 않았습니다.
이치노

이것은 우리에게 효과가 있었습니다.

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonIgnoreProperties({"success", "deleted"}) // <- Prevents serialization duplicates 
public class MyResponse {

    private String id;
    private @JsonProperty("isSuccess") boolean isSuccess; // <- Forces field name
    private @JsonProperty("isDeleted") boolean isDeleted;

}

Utkarsh의 대답을 바탕으로...

getter name에서 get/is를 뺀 이 JSON 이름으로 사용됩니다.

public class Example{
    private String radcliffe; 

    public getHarryPotter(){
        return radcliffe; 
    }
}

{harryPotter}: "YouGaveHere" 로 저장됩니다.


역직렬화의 경우 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 ; 
    }
}

더 흥미로운 질문은 잭슨이 탈직렬화를 위해 어떤 순서를 고려하느냐는 것이다.{"word1" : "myName"}을(를) 역직렬화하려고 하면

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

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

저는 위의 사례를 테스트하지 않았지만, word1과 word2의 을 보는 것은 흥미롭습니다.

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

프리미티브 부울을 java.lang으로 변경할 수 있습니다.부울(+사용)@JsonPropery)

@JsonProperty("isA")
private Boolean isA = false;

public Boolean getA() {
    return this.isA;
}

public void setA(Boolean a) {
    this.isA = a;
}

나한테는 아주 잘 먹혔어.

자신의 관리 하에 있지 않은 서드파티 클래스(댓글에서 언급한@edmundpie 등)를 처리하는 데 관심이 있는 경우 오브젝트매퍼에 Mixin 클래스를 추가합니다.여기서 속성/필드 이름은 서드파티 클래스의 이름과 일치해야 합니다.

public class MyStack32270422 {

  public static void main(String[] args) {
    ObjectMapper om3rdParty = new ObjectMapper();
    om3rdParty .addMixIn(My3rdPartyResponse.class, MixinMyResponse.class);
    // add further mixins if required
    String jsonString = om3rdParty.writeValueAsString(new My3rdPartyResponse());
    System.out.println(jsonString);
  }
}

class MixinMyResponse {
  // add all jackson annotations here you want to be used when handling My3rdPartyResponse classes
  @JsonProperty("isSuccess")
  private boolean isSuccess;
}

class My3rdPartyResponse{
  private boolean isSuccess = true;
  // getter and setter here if desired
}

기본적으로는 모든 잭슨 주석을 Mixin 클래스에 추가합니다.클래스를 소유하는 것처럼요."is..."로 시작하는 방법 이름을 확인하는 데 시간을 낭비할 필요가 없기 때문에 제 생각에는 꽤 좋은 해결책입니다.기타 등등.

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

새로운 서브클래스를 정의하고 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;
        }
    });

내 경우엔 받아들여진 답이 통하지 않을 것이다.

나의 경우, 그 수업은 내가 소유하지 않는다.문제가 되는 클래스는 서드파티 의존관계이기 때문에 그냥 추가할 수 없습니다.@JsonProperty주석을 달아야 합니다.

이를 해결하기 위해 위의 @burak 답변에서 영감을 얻어 커스텀을 만들었습니다.PropertyNamingStrategy다음과 같습니다.

mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
  @Override
  public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
  {
    if (method.getParameterCount() == 1 &&
            (method.getRawParameterType(0) == Boolean.class || method.getRawParameterType(0) == boolean.class) &&
            method.getName().startsWith("set")) {

      Class<?> containingClass = method.getDeclaringClass();
      String potentialFieldName = "is" + method.getName().substring(3);

      try {
        containingClass.getDeclaredField(potentialFieldName);
        return potentialFieldName;
      } catch (NoSuchFieldException e) {
        // do nothing and fall through
      }
    }

    return super.nameForSetterMethod(config, method, defaultName);
  }

  @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")) {

      Class<?> containingClass = method.getDeclaringClass();
      String potentialFieldName = method.getName();

      try {
        containingClass.getDeclaredField(potentialFieldName);
        return potentialFieldName;
      } catch (NoSuchFieldException e) {
        // do nothing and fall through
      }
    }
    return super.nameForGetterMethod(config, method, defaultName);
  }
});

기본적으로 이것은 시리얼화 및 역직렬화 전에 타겟/소스 클래스에서 어떤 속성 이름이 클래스에 존재하는지 여부를 확인합니다.isEnabled또는enabled소유물.

이를 기반으로 매퍼는 존재하는 속성 이름으로 직렬화 및 직렬화 해제됩니다.

언급URL : https://stackoverflow.com/questions/32270422/jackson-renames-primitive-boolean-field-by-removing-is

반응형