Hvordan Serialize og Deserialize Enums med Jackson

1. Oversikt

Denne raske opplæringen viser hvordan du styrer veien Java Enums serialiseres og deserialiseres med Jackson 2.

Å grave litt dypere og lære andre kule ting vi kan gjøre Jackson 2 - gå videre til hovedveiledningen for Jackson.

2. Kontrollere Enum-representasjonen

La oss definere følgende Enum:

offentlig enum Avstand {KILOMETER ("km", 1000), MILE ("miles", 1609.34), METER ("meter", 1), INCH ("inches", 0.0254), CENTIMETER ("cm", 0.01), MILLIMETER ("mm", 0,001); privat streng enhet; private endelige dobbelt meter; privat avstand (streng enhet, dobbel meter) {this.unit = enhet; this.meters = meter; } // standard getters and setters}

3. Serialisere Enums til JSON

3.1. Standard Enum Representasjon

Som standard vil Jackson representere Java Enums som enkel streng - for eksempel:

ny ObjectMapper (). writeValueAsString (Distance.MILE);

Vil resultere i:

"MILE"

Hva vi ønsker å få når vi marsjerer dette Enum til et JSON-objekt er å gi noe sånt som:

{"unit": "miles", "meters": 1609.34} 

3.2. Enum som JSON-objekt

Fra og med Jackson 2.1.2 er det nå et konfigurasjonsalternativ som kan håndtere denne typen representasjon. Dette kan gjøres via @JsonFormat kommentar på klassenivå:

@JsonFormat (form = JsonFormat.Shape.OBJECT) offentlig enum Avstand {...}

Dette vil føre til ønsket resultat når du serierer dette enum til Avstand.MILE:

{"unit": "miles", "meters": 1609.34}

3.3. Enums og @JsonValue

Nok en enkel måte å kontrollere marshaling-utgangen for en enum er å bruke @JsonValue kommentar på en getter:

offentlig enum Distance {... @JsonValue public String getMeters () {return meters; }}

Det vi uttrykker her er at getMeters () er den faktiske representasjonen av dette enum. Så resultatet av serialisering vil være:

1609.34

3.4. Custom Serializer for Enum

Før Jackson 2.1.2, eller hvis det kreves enda mer tilpasning for enum, kan vi bruke a tilpasset Jackson-seriell. Først må vi definere det:

offentlig klasse DistanceSerializer utvider StdSerializer {offentlig DistanceSerializer () {super (Distance.class); } offentlig DistanceSerializer (klasse t) {super (t); } public void serialize (Distance distance, JsonGenerator generator, SerializerProvider provider) kaster IOException, JsonProcessingException {generator.writeStartObject (); generator.writeFieldName ("navn"); generator.writeString (avstand.navn ()); generator.writeFieldName ("enhet"); generator.writeString (distance.getUnit ()); generator.writeFieldName ("meter"); generator.writeNumber (distance.getMeters ()); generator.writeEndObject (); }}

Vi vil nå bruke serialisereren på klassen som skal serienummeres:

@JsonSerialize (ved hjelp av = DistanceSerializer.class) offentlig enum TypeEnum {...}

Som resulterer i:

{"name": "MILE", "unit": "miles", "meters": 1609.34}

4. Deserialisere JSON til Enum

La oss først definere en By klasse som har en Avstand medlem:

offentlig klasse By {privat Avstand avstand; ...}

Deretter diskuterer vi de forskjellige måtene å deserialisere en JSON-streng til en Enum.

4.1. Standard atferd

Som standard vil Jackson bruke Enum-navnet til å deserialisere fra JSON.

For eksempel vil den deserialisere JSON:

{"distance": "KILOMETER"}

Til en Avstand.KILOMETER gjenstand:

Byby = ny ObjectMapper (). ReadValue (json, City.class); assertEquals (Distance.KILOMETER, city.getDistance ());

4.2. Ved hjelp av @JsonValue

Vi har lært å bruke @JsonValue å serieisere Enums. Vi kan også bruke den samme merknaden for deserialisering. Dette er mulig fordi Enum-verdier er konstanter.

La oss først bruke @JsonValue med en av gettermetodene - getMeters ():

public enum Distance {... @JsonValue public double getMeters () {return meters; }}

Nå, returverdien av getMeters () metoden representerer Enum-objektene. Når du deserialiserer prøven JSON:

{"distance": "0.0254"}

Jackson vil se etter Enum-objektet som har en getMeters () returverdi på 0,0254. I dette tilfellet er objektet det Avstand.TOMMER:

assertEquals (Distance.INCH, city.getDistance ()); 

4.3. Ved hjelp av @JsonProperty

De @JsonProperty kommentar brukes i oppregningsforekomster:

offentlig enum Distance {@JsonProperty ("distance-in-km") KILOMETER ("km", 1000), @JsonProperty ("distance-in-miles") MILE ("miles", 1609.34); ...}

Ved å bruke denne merknaden, vi ber ganske enkelt Jackson om å kartlegge verdien av @JsonProperty til objektet som er merket med denne verdien.

Som et resultat av ovennevnte erklæring, er eksemplet JSON-streng:

{"distance": "distance-in-km"}

Vil bli kartlagt til Avstand.KILOMETER gjenstand:

assertEquals (Distance.KILOMETER, city.getDistance ());

4.4. Ved hjelp av @JsonCreator

Jackson påkaller metoder merket med @JsonCreator for å få en forekomst av den vedlagte klassen.

Vurder JSON-representasjonen:

{"distance": {"unit": "miles", "meters": 1609.34}}

La oss nå definere forValues ​​() fabrikkmetode med @JsonCreator kommentar:

public enum Distance {@JsonCreator public static Distance forValues ​​(@JsonProperty ("unit") Strengenhet, @JsonProperty ("meter") doble meter) {for (Distance distance: Distance.values ​​()) {if (distance.unit. er lik (enhet) && Double.compare (distance.meters, meter) == 0) {retur avstand; }} returner null; } ...}

Legg merke til bruken av @JsonProperty merknad for å binde JSON-feltene med metodeargumentene.

Så når vi deserialiserer JSON-prøven, får vi resultatet:

assertEquals (Distance.MILE, city.getDistance ());

4.5. Bruke en egendefinert Deserializer

En tilpasset deserializer kan brukes hvis ingen av de beskrevne teknikkene er tilgjengelige. For eksempel har vi kanskje ikke tilgang til Enum-kildekoden, eller vi bruker kanskje en eldre Jackson-versjon som ikke støtter en eller flere av kommentarene som er dekket så langt.

I henhold til vår tilpassede deserialiseringsartikkel, for å deserialisere JSON som er gitt i forrige avsnitt, begynner vi med å lage deserialiseringsklassen:

offentlig klasse CustomEnumDeserializer utvider StdDeserializer {@ Override public Distance deserialize (JsonParser jsonParser, DeserializationContext ctxt) kaster IOException, JsonProcessingException {JsonNode node = jsonParser.getCodec (). readTree (; jsonPars) Strengenhet = node.get ("enhet"). AsText (); doble meter = node.get ("meter"). asDouble (); for (Distance distance: Distance.values ​​()) {if (distance.getUnit (). er lik (enhet) && Double.compare (distance.getMeters (), meter) == 0) {returavstand; }} returner null; }} 

Deretter bruker vi @JsonDeserialize kommentar på Enum for å spesifisere vår tilpassede deserializer:

@JsonDeserialize (ved hjelp av = CustomEnumDeserializer.class) offentlig enum Avstand {...}

Og resultatet vårt er:

assertEquals (Distance.MILE, city.getDistance ());

5. Konklusjon

Denne artikkelen illustrerte hvordan du kan få bedre kontroll over serie- og deserialiseringsprosesser og formater av Java Enums.

Implementeringen av alle disse eksemplene og kodebiter finner du på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found