2016-11-03 6 views
3

Ich habe eine Java-Klasse mit einem optionalen Feld. Ich bin die Klasse zu JSON mit Jackson 2.8.3 (aufgerufen von Spring Web 4.3.3).Wie überspringe ich optionale.leere Felder während der Jackson-Serialisierung?

Ich hoffe, den Serializer das Feld zu überspringen, wenn das Optional leer ist, und die enthaltene Zeichenfolge serialisieren, wenn es vorhanden ist. Ein Beispiel für das Ergebnis, denn ich bin auf der Suche mit einer Liste von zwei Objekten:

[ 
    { 
     "id": 1, 
     "foo": "bar" 
    }, 
    { 
     "id": 2, 
    } 
] 

Hier die foo Optional ist leer für das Objekt mit der ID 2.

Statt dessen, was ich bekommen ist:

[ 
    { 
     "id": 1, 
     "foo": { 
      "present": true 
     } 
    }, 
    { 
     "id": 2, 
     "foo": { 
      "present": false 
     } 
    } 
] 

Dies ist das Ergebnis, auch wenn ich das „bar“ Feld in der Klasse wie

@JsonInclude(JsonInclude.Include.NON_ABSENT) 
public Optional<String> getFoo() { ... 

jede wa gibt es annotieren y Kann ich ein Ergebnis wie die erste Liste mit den Jackson-Anmerkungen oder einem benutzerdefinierten Serializer erzielen?

+1

Die Verwendung von 'Optional' als Feld einer Bean ist im Allgemeinen eine schlechte Idee. – biziclop

+0

Warum wird das als problematisch angesehen? –

+0

Es wurde nicht für diese Art der Verwendung entwickelt. Es ist ein sehr subtiler semantischer Unterschied, aber im Falle eines Feldes wird "null" nur als ein anderer Wert betrachtet. Wenn Sie eine Methode in der API einer Bibliothek entwerfen, sollten Sie jedoch betonen, dass sie möglicherweise keinen Wert zurückgibt und daher "Optional" verwendet. Sehen Sie mehr [hier] (http://stackoverflow.com/questions/26327957/should-java-8-getters-return-optional-type/26328555#26328555) – biziclop

Antwort

1

Verwenden Sie eine JsonSerializer für Ihre Bedürfnisse.

So etwas wie diese (halb-Pseudo-):

public class MySer extends JsonSerializer<Opional<?>> { 

     @Override 
     public void serialize(Optional<?> optString, JsonGenerator generator, SerializerProvider provider) 
              throws IOException, JsonProcessingException { 
     //Check Optional here...   
     generator.writeString(/* DO SOMETHING HERE WHATEVER */); 
    } 

// Dann in Ihrem Modell:

public class ClassWhatever {   
    @JsonSerialize(using = MySer .class) 
    public Optional<String> getFoo() { ... 
} 

mit @JsonSerialize jedes Feld mit Anmerkungen versehen, um zu vermeiden Sie Ihre benutzerdefinierten Serializer Objekt registrieren können Mapper mit

ObjectMapper mapper = new ObjectMapper(); 
SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null)); 
testModule.addSerializer(new MyCustomSerializer()); // assuming serializer declares correct class to bind to 
mapper.registerModule(testModule); 

Auch angegebene Lösung funktioniert nur für die Serialisierung. Die Deserialisierung schlägt fehl, wenn Sie nicht Ihren eigenen Deserializer schreiben. Dann müssen Sie jedes Feld mit @JsonDeserializ e annotieren oder registrieren Sie Ihren benutzerdefinierten Deserializer.

+0

com.fasterxml.jackson.datatype: jackson-datatype-jdk8 ist eine bessere Option. Bei einer solchen benutzerdefinierten Lösung müssen Sie jedes Feld mit Anmerkungen versehen. Die Deserialisierung wird auch nicht funktionieren, wenn Sie keinen benutzerdefinierten Deserializer schreiben und jedes Feld mit @JsonDeserialize versehen. –

+0

@BartoszBilicki Sicher, in Übereinstimmung mit Ihnen. Beide würden funktionieren, aber Ihre Empfehlung ist besser. – Mechkov

8

Keine Notwendigkeit, benutzerdefinierten Serializer zu schreiben. Beschriften Sie Ihre Klasse mit @JsonInclude(JsonInclude.Include.NON_NULL). NON_ABSENT und NON_EMPTY wird auch gut funktionieren.

Sie müssen auch com.fasterxml.jackson.datatype:jackson-datatype-jdk8 als Ihre Abhängigkeit einschließen.

+0

Danke, einschließlich der Abhängigkeit von com.fasterxml.jackson.datatype: jackson-datatype-jdk8 hat den Trick gemacht. –

+0

@ JsonInclude (JsonInclude.Include.NON_ABSENT) wird gut genug sein. – GKVM

Verwandte Themen