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.