2014-12-06 7 views
2

У меня проблема, с которой я не могу решить какое-то время. Позволяет себе очень простой Java-классЧастичная сериализация/де-сериализация JSON с использованием Jackson

class Foo { 
    public String bar; 
    public String baz; 
} 

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

{ 
    "bar": "some value", 
    "baz": null 
} 

в экземпляр Foo, а затем сериализация его обратно в формат JSON, я получаю

{ 
    "bar": "some value", 
    "baz": null 
} 

и если я десериализируюсь частичное JSON без "БАЗ"

{ 
    "bar": "some value" 
} 

I снова получить частичный JSON без «baz»

{ 
    "bar": "some value" 
} 

ответ

1

Это невозможно, если вы не храните информацию о том, какие поля присутствовали в исходных объектах JSON. Для этой цели вы можете использовать обертку около Foo, которая содержит Foo плюс эту дополнительную информацию. Ниже приведен пример.

Примечание: это pseudocode. Имена методов и классов являются частью библиотеки Gson и частью, придуманной мной на лету, но вы получаете эту идею. Я думаю, что это не составит труда перевести это, используя классы Джексона.

class DeserializedFoo { 

    private Foo foo; 
    private Set<String> includedFields = new HashSet<>(); 

    private DeserializedFoo(){ 

    } 

    public static class DeSerializer implements JsonDeserializer<DeserializedFoo> { 
     @Override 
     public DeserializedFoo deserialize(JsonElement je) { 
      DeserializedFoo dsFoo = new DeserializedFoo(); 
      dsFoo.foo = parse(je); 
      for(JsonElement prop : je.elements()){ 
       includedFields.add(prop.getName()); 
      } 
      return dsFoo; 
     } 
    } 

    public static class Serializer implements JsonSerializer<DeserializedFoo> { 
     @Override 
     public JsonElement serialize(DeserializedFoo dsFoo) { 
      JsonElement jsonFoo = serialize(dsFoo.foo); 

      // Leave only fields that were present in the JSON 
      // element from which this was deserialized. 
      Iterable it = jsonFoo.elements().iterable(); 
      while(it.hasNext()){ 
       JsonElement prop = it.next(); 
       if(!includedFields.contains(prop.getName()){ 
        it.remove(); 
       } 
      } 
      return jsonFoo; 
     } 
    } 
} 

Вы можете, конечно, использовать наследование вместо обертки, например. путем определения class DeserilizedFoo extends Foo и добавления поля includedFields. Каждый подход имеет свои преимущества и недостатки. Вам решать, какой из них лучше всего подходит для вашей ситуации.

1

Вы можете аннотированный свой класс с @JsonInclude(Include.NON_DEFAULT) и установить значение по умолчанию для baz собственности волшебную строку, которая указывает на то, что значение не должно присутствовать в формате JSON.

Вот пример:

public class JacksonIncludeNull { 

    final static String JSON1 = "{\n" + 
      " \"bar\": \"some value\",\n" + 
      " \"baz\": null\n" + 
      "}"; 

    final static String JSON2 = "{\n" + 
      " \"bar\": \"some value\"\n" + 
      "}"; 

    @JsonInclude(JsonInclude.Include.NON_DEFAULT) 
    static class Foo { 
     public String bar; 
     public String baz = "##default"; 

     @Override 
     public String toString() { 
      return "Foo{" + 
        "bar='" + bar + '\'' + 
        ", baz='" + baz + '\'' + 
        '}'; 
     } 
    } 

    public static void main(String[] args) throws IOException { 
     final ObjectMapper mapper = new ObjectMapper(); 
     mapper.registerModule(new GuavaModule()); 
     final Foo foo1 = mapper.readValue(JSON1, Foo.class); 
     System.out.println(JSON1); 
     System.out.println("Object: " + foo1); 
     System.out.println("Serialize: " + mapper.writeValueAsString(foo1)); 

     System.out.println(); 

     final Foo foo2 = mapper.readValue(JSON2, Foo.class); 
     System.out.println(JSON2); 
     System.out.println("Object: " + foo2); 
     System.out.println("Serialize: " + mapper.writeValueAsString(foo2)); 
    } 
} 

Выход:

{ 
    "bar": "some value", 
    "baz": null 
} 
Object: Foo{bar='some value', baz='null'} 
Serialize: {"bar":"some value","baz":null} 

{ 
    "bar": "some value" 
} 
Object: Foo{bar='some value', baz='##default'} 
Serialize: {"bar":"some value"} 
Смежные вопросы