Programing

Jackson 직렬화 : 빈 값 무시 (또는 null)

lottogame 2020. 7. 3. 18:41
반응형

Jackson 직렬화 : 빈 값 무시 (또는 null)


현재 jackson 2.1.4를 사용하고 있으며 객체를 JSON 문자열로 변환 할 때 필드를 무시하는 데 문제가 있습니다.

변환 할 객체로 작동하는 클래스는 다음과 같습니다.

public class JsonOperation {

public static class Request {
    @JsonInclude(Include.NON_EMPTY)
    String requestType;
    Data data = new Data();

    public static class Data {
        @JsonInclude(Include.NON_EMPTY)
        String username;
        String email;
        String password;
        String birthday;
        String coinsPackage;
        String coins;
        String transactionId;
        boolean isLoggedIn;
    }
}

public static class Response {
    @JsonInclude(Include.NON_EMPTY)
    String requestType = null;
    Data data = new Data();

    public static class Data {
        @JsonInclude(Include.NON_EMPTY)
        enum ErrorCode { ERROR_INVALID_LOGIN, ERROR_USERNAME_ALREADY_TAKEN, ERROR_EMAIL_ALREADY_TAKEN };
        enum Status { ok, error };

        Status status;
        ErrorCode errorCode;
        String expiry;
        int coins;
        String email;
        String birthday;
        String pictureUrl;
        ArrayList <Performer> performer;
    }
}
}

그리고 그것을 변환하는 방법은 다음과 같습니다.

ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

JsonOperation subscribe = new JsonOperation();

subscribe.request.requestType = "login";

subscribe.request.data.username = "Vincent";
subscribe.request.data.password = "test";


Writer strWriter = new StringWriter();
try {
    mapper.writeValue(strWriter, subscribe.request);
} catch (JsonGenerationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (JsonMappingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Log.d("JSON", strWriter.toString())

출력은 다음과 같습니다.

{"data":{"birthday":null,"coins":null,"coinsPackage":null,"email":null,"username":"Vincent","password":"test","transactionId":null,"isLoggedIn":false},"requestType":"login"}

이러한 null 값을 피하려면 어떻게해야합니까? "구독"목적으로 만 필요한 정보를 얻고 싶습니다!

내가 찾는 결과는 다음과 같습니다.

{"data":{"username":"Vincent","password":"test"},"requestType":"login"}

또한 @JsonInclude (Include.NON_NULL)을 시도하고 모든 변수를 null로 설정했지만 작동하지 않았습니다! 도와 주셔서 감사합니다!


잘못된 위치에 주석이 있습니다. 필드가 아니라 클래스에 있어야합니다. 즉 :

@JsonInclude(Include.NON_NULL) //or Include.NON_EMPTY, if that fits your use case 
public static class Request {
  // ...
}

주석에서 언급했듯이 버전 2.x +에서이 주석의 구문은 다음과 같습니다.

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) // or JsonSerialize.Inclusion.NON_EMPTY

The other option is to configure the ObjectMapper directly, simply by calling mapper.setSerializationInclusion(Include.NON_NULL);

(for the record, I think the popularity of this answer is an indication that this annotation should be applicable on a field-by-field basis *ahem @fasterxml*)


You can also set the global option:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

Also you can try to use

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

if you are dealing with jackson with version below 2+ (1.9.5) i tested it, you can easily use this annotation above the class. Not for specified for the attributes, just for class decleration.


You need to add import com.fasterxml.jackson.annotation.JsonInclude;

Add

@JsonInclude(JsonInclude.Include.NON_NULL)

on top of POJO

If you have nested POJO then

@JsonInclude(JsonInclude.Include.NON_NULL)

need to add on every values.

NOTE: JAXRS (Jersey ) automatically handle this scenario 2.6 and above.


For jackson 2.x

@JsonInclude(JsonInclude.Include.NON_NULL) just before the field.


I was having similar problem recently with version 2.6.6.

@JsonInclude(JsonInclude.Include.NON_NULL)

Using above annotation either on filed or class level was not working as expected. The POJO was mutable where I was applying the annotation. When I changed the behaviour of the POJO to be immutable the annotation worked its magic.

I am not sure if its down to new version or previous versions of this lib had similar behaviour but for 2.6.6 certainly you need to have Immutable POJO for the annotation to work.

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

Above option mentioned in various answers of setting serialisation inclusion in ObjectMapper directly at global level works as well but, I prefer controlling it at class or filed level.

So if you wanted all the null fields to be ignored while JSON serialisation then use the annotation at class level but if you want only few fields to ignored in a class then use it over those specific fields. This way its more readable & easy for maintenance if you wanted to change behaviour for specific response.


Or you can use GSON [https://code.google.com/p/google-gson/], where these null fields will be automatically removed.

SampleDTO.java

public class SampleDTO {

    String username;
    String email;
    String password;
    String birthday;
    String coinsPackage;
    String coins;
    String transactionId;
    boolean isLoggedIn;

    // getters/setters
}

Test.java

import com.google.gson.Gson;

public class Test {

    public static void main(String[] args) {
        SampleDTO objSampleDTO = new SampleDTO();
        Gson objGson = new Gson();
        System.out.println(objGson.toJson(objSampleDTO));
    }
}

OUTPUT:

{"isLoggedIn":false}

I used gson-2.2.4


Code bellow may help if you want to exclude boolean type from serialization either:

@JsonInclude(JsonInclude.Include.NON_ABSENT)

참고URL : https://stackoverflow.com/questions/16089651/jackson-serialization-ignore-empty-values-or-null

반응형