Сеансирование Джексона: игнорировать пустые значения (или 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"}

Как я могу избежать этих нулевых значений? Я хочу получить только необходимую информацию для подписки!

Вот именно тот вывод, который я ищу:

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

Я также попытался @JsonInclude (Include.NON_NULL) и установил все мои переменные в null, но это тоже не сработало! Спасибо за помощь ребята!

Ответ 1

У вас есть аннотация не в том месте - она должна быть в классе, а не в поле. то есть:

@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

Другой вариант - настроить ObjectMapper напрямую, просто вызвав mapper.setSerializationInclusion(Include.NON_NULL);

(для справки, я думаю, что популярность этого ответа является показателем того, что эта аннотация должна быть применима для каждого поля в отдельности * ahem @fastxml *)

Ответ 2

Вы также можете установить глобальную опцию:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

Ответ 3

Также вы можете попробовать использовать

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

если вы имеете дело с jackson с версией ниже 2+ (1.9.5), которую я тестировал, вы можете легко использовать эту аннотацию выше класса. Не для указанных атрибутов, просто для объявления класса.

Ответ 4

Вам нужно добавить import com.fasterxml.jackson.annotation.JsonInclude;

Добавить

@JsonInclude(JsonInclude.Include.NON_NULL)

поверх POJO

Если у вас есть вложенный POJO, то

@JsonInclude(JsonInclude.Include.NON_NULL)

необходимо добавить к каждому значению.

Примечание: JAXRS (Джерси) автоматически обрабатывает этот сценарий 2.6 и выше.

Ответ 5

Для jackson 2.x

@JsonInclude (JsonInclude.Include.NON_NULL) непосредственно перед полем.

Ответ 6

Или вы можете использовать GSON [https://code.google.com/p/google-gson/], где эти пустые поля будут автоматически удалены.

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));
    }
}

ВЫВОД:

{"isLoggedIn":false}

Я использовал gson-2.2.4

Ответ 7

У меня была аналогичная проблема с версией 2.6.6.

@JsonInclude(JsonInclude.Include.NON_NULL)

Использование выше аннотации либо на поданном, либо на уровне класса не работает должным образом. POJO был изменен, когда я применял аннотацию. Когда я изменил поведение POJO на неизменное, аннотация обработала его магию.

Я не уверен, что его работа с новой версией или предыдущими версиями этой библиотеки имела аналогичное поведение, но для 2.6.6, конечно, вам нужно иметь Immutable POJO для работы аннотации.

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

Вышеупомянутый параметр, упомянутый в различных ответах на включение включения сериализации в ObjectMapper непосредственно на глобальном уровне, также работает, но я предпочитаю контролировать его на уровне класса или уровня.

Итак, если вы хотите, чтобы все пустые поля игнорировались во время сериализации JSON, используйте аннотацию на уровне класса, но если вы хотите игнорировать только несколько полей в классе, используйте его в этих конкретных полях. Таким образом, он более читабельный и простой в обслуживании, если вы хотите изменить поведение для конкретного ответа.

Ответ 8

это может быть достигнуто двумя способами:

  • Отметьте POJO, чтобы игнорировать свойства null/empty

    import com.fasterxml.jackson.annotation.JsonInclude
    
    @JsonInclude(Include.NON_NULL) // or @JsonInclude(Include.NON_EMPTY)
    
  • Настройте ObjectMapper, который сериализует POJO/json, как показано ниже:

    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    ObjectMapper mapper = new ObjectMapper();            
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    

Ответ 9

Код ниже может помочь, если вы хотите исключить логический тип из сериализации:

@JsonInclude(JsonInclude.Include.NON_ABSENT)