2013-04-18 5 views
95

В настоящее время я использую jackson 2.1.4, и у меня возникают проблемы с игнорированием полей, когда я конвертирую объект в строку JSON.Сериализация Джексона: игнорировать пустые значения (или null)

Вот мой класс, который действует как объект, который будет преобразован:

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) и поставить все свои переменные нуль, но это не сработало! Спасибо за помощь ребята!

ответ

178

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

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

Как было отмечено в комментариях, в версии 2.х + синтаксис этой аннотации:

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

Другой вариант заключается в настройке ObjectMapper напрямую, просто позвонив по телефону mapper.setSerializationInclusion(Include.NON_NULL);

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

+0

Там действительно нет способа сделать аннотацию include.NON_NULL работать? Или NON_EMTPY? Потому что я знаю, какой из них будет пустым, но это зависит от ситуации.Я использую тот же класс «JsonOperation» для каждого объекта, который я хочу сериализовать/десериализовать, и я только инициализирую переменные, которые мне нужно использовать, в зависимости от ситуации. Это хороший способ сделать это, или я должен делать классы с несколькими классами, содержащие только те переменные, которые мне нужны (таким образом мне не нужно было бы использовать какую-либо аннотацию, так как никогда не будет пустой/пустой переменной) – Shinnyx

+0

Ahhh sorry, I Посмотрите, что происходит сейчас. См. Мой отредактированный ответ. – drewmoore

+0

Получил работу! Я не могу поверить, что это проблема ... Спасибо, спасибо! – Shinnyx

40

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

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 
13

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

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 

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

+1

include атрибут JsonSerialize не рекомендуется в пользу JsonInclude – fd8s0

+2

, как я сказал: с jackson с версией ниже 2+ (1.9.5) – erhan

+0

вопрос задает вопрос о конкретной версии 2.1.4 – fd8s0

3

Или вы можете использовать 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

+0

Фактически проект теперь использует GSON. Ничего плохого в игре с Джексоном, но некоторые ошибки, связанные с Android, были решены с помощью GSON в моем личном опыте. Спасибо, что заработали! Upvoted. – Shinnyx

5

Для JACKSON 2.х

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

9

Вам необходимо добавить импорт com.fasterxml.jackson.annotation.JsonInclude;

Добавить

@JsonInclude(JsonInclude.Include.NON_NULL) 

на вершине POJO

Если у вас есть вложенные Pojo затем

@JsonInclude(JsonInclude.Include.NON_NULL) 

нужно добавлять на каждые значения.

ПРИМЕЧАНИЕ: JAXRS (Джерси) автоматически обрабатывает этот сценарий 2.6 и выше.

+0

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

+0

Да, вы можете добавить поверх примера метода getter private int id; @JsonIgnore public int getId() { return id; } –

2

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

@JsonInclude(JsonInclude.Include.NON_NULL) 

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

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

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 

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

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

0

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

  1. Марк POJO игнорировать неопределенные/пустые свойства

    import com.fasterxml.jackson.annotation.JsonInclude 
    
    @JsonInclude(Include.NON_NULL) // or @JsonInclude(Include.NON_EMPTY) 
    
  2. Настройка 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); 
    
0

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

@JsonInclude(JsonInclude.Include.NON_ABSENT) 
Смежные вопросы