Серіялізація Джексона: ігноруйте порожні значення (або нульові)


138

Наразі я використовую 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) і поставив всі мої змінні на нуль, але це також не вийшло! Дякую за допомогу, хлопці!


Відповіді:


247

Анотацію ви маєте не в тому місці - вона повинна бути на уроці, а не на полі. тобто:

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

(для запису, я вважаю, що популярність цієї відповіді є свідченням того, що ця анотація повинна застосовуватися по польовій основі, @fasterxml)


Дійсно не можна зробити анотацію include.NON_NULL працювати? Або NON_EMTPY? Тому що я знаю, який з них буде нульовим, але це залежить від ситуації. Я використовую той самий клас "JsonOperation" для кожного об'єкта, який я хочу серіалізувати / десеріалізувати, і я ініціалізую лише ті змінні, які мені потрібно використовувати залежно від ситуації. Це хороший спосіб зробити це, або я повинен робити кілька класів, що містять лише потрібні мені змінні (таким чином я не мав би використовувати жодної анотації, оскільки ніколи не буде нульової / порожньої змінної)
Shinnyx

26
Синтаксис змінився в останній версії на @JsonSerialize (включати = JsonSerialize.Inclusion.NON_NULL) і @JsonSerialize (включати = JsonSerialize.Inclusion.NON_EMPTY Якщо вам потрібно і ненулеве, і не порожнє, використовуйте @JsonSerialize (включайте = JsonSerialize .Inclusion.NON_DEFAULT)
Maciej

1
Використовуйте @JsonSerialize (включайте = включення.NON_NULL) перед класом або перед тим, як він працював ...
лебідь

1
@drewmoore перевірте ще раз, @JsonInclude(JsonSerialize.Inclusion.NON_NULL) має бути, @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)а також це старий застарілий спосіб. тож ви повинні писати "у версії нижче 2.x", а не "у версії 2.x +"
WestFarmer

2
2. + використання@JsonInclude(Include.NON_NULL)
Honghe.Wu

48

Ви також можете встановити глобальний варіант:

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

15

Також ви можете спробувати використовувати

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

якщо ви маєте справу з Джексоном з версією нижче 2+ (1.9.5), яку я перевірив, ви можете легко використовувати цю анотацію вище класу. Не вказано для атрибутів, а лише для декларування класу.


2
включати атрибут JsonSerialize є застарілим на користь JsonInclude
fd8s0

2
як я сказав: з Джексоном з версією нижче 2+ (1.9.5)
erhanasikoglu

у запитанні йдеться про конкретну версію 2.1.4
fd8s0

14

Вам потрібно додати import com.fasterxml.jackson.annotation.JsonInclude;

Додайте

@JsonInclude(JsonInclude.Include.NON_NULL)

поверх POJO

Якщо ви вклали POJO тоді

@JsonInclude(JsonInclude.Include.NON_NULL)

потрібно додавати всі значення.

ПРИМІТКА. JAXRS (Джерсі) автоматично обробляє цей сценарій 2.6 і вище.


чи існує аналогічна функціональність при використанні старого пакету org.codehaus.jackson.annotate?
pkran

Так, ви можете додати поверх прикладного методу getter приклад private int id; @JsonIgnore public int getId () {return id; }
ваквар хан

1
Те саме, що є відповіді
Карл Ріхтер


2

У мене були подібні проблеми нещодавно з версією 2.6.6.

@JsonInclude(JsonInclude.Include.NON_NULL)

Використання вищеописаних приміток на рівні поданих чи класових робіт не працює, як очікувалося. POJO було вимкнено, де я застосовував анотацію. Коли я змінив поведінку POJO, щоб бути незмінним, анотація працювала своєю магією.

Я не впевнений, чи відносяться до нової версії або попередніх версій цього файлу подібну поведінку, але для 2.6.6, безумовно, вам потрібно мати Immutable POJO, щоб анотація працювала.

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

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

Отже, якщо ви хотіли, щоб під час серіалізації JSON усі ініціальні поля були ігноровані, тоді використовуйте примітку на рівні класу, але якщо ви хочете лише ігнорувати лише декілька полів у класі, тоді використовуйте їх у цих конкретних полях. Таким чином, його легше читати та легше обслуговувати, якщо ви хочете змінити поведінку для конкретного реагування.


2

Або ви можете використовувати 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


-1

Нижче наведений код може допомогти, якщо ви хочете виключити булевий тип із серіалізації:

@JsonInclude(JsonInclude.Include.NON_ABSENT)

1
Те саме, що є відповіді
Карл Ріхтер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.