Sådan serialiseres og deserialiseres Enums med Jackson

1. Oversigt

Denne hurtige vejledning viser, hvordan du styrer vejen Java Enums serialiseres og deserialiseres med Jackson 2.

At grave lidt dybere og lære andre seje ting, vi kan gøre Jackson 2 - gå videre til den vigtigste Jackson-tutorial.

2. Styring af Enum-repræsentationen

Lad os definere følgende Enum:

offentlig enum Distance {KILOMETER ("km", 1000), MILE ("miles", 1609.34), METER ("meter", 1), INCH ("inches", 0.0254), CENTIMETER ("cm", 0.01), MILLIMETER ("mm", 0,001); privat streng enhed; private sidste dobbelt meter; privat afstand (streng enhed, dobbelt meter) {this.unit = enhed; this.meters = meter; } // standard getters og setters}

3. Serialisering af Enums til JSON

3.1. Standard Enum-repræsentation

Som standard vil Jackson repræsentere Java Enums som simpel streng - for eksempel:

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

Vil medføre:

"MIL"

Hvad vi gerne vil have, når vi marcherer dette Enum til et JSON-objekt er at give noget som:

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

3.2. Enum som JSON-objekt

Fra og med Jackson 2.1.2 er der nu en konfigurationsmulighed, der kan håndtere denne form for repræsentation. Dette kan gøres via @JsonFormat kommentar på klasseniveau:

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

Dette vil føre til det ønskede resultat, når du serialiserer dette enum til Afstand.MIL:

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

3.3. Enums og @JsonValue

Endnu en anden enkel måde at kontrollere marshaling-output for en enum er at bruge @JsonValue kommentar på en getter:

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

Det, vi udtrykker her, er det getMeters () er den aktuelle repræsentation af dette enum. Så resultatet af serialisering vil være:

1609.34

3.4. Custom Serializer til Enum

Før Jackson 2.1.2, eller hvis der kræves endnu mere tilpasning til enummet, kan vi bruge en brugerdefineret Jackson serializer. Først skal vi definere det:

offentlig klasse DistanceSerializer udvider StdSerializer {public 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 (distance.name ()); generator.writeFieldName ("enhed"); generator.writeString (distance.getUnit ()); generator.writeFieldName ("meter"); generator.writeNumber (distance.getMeters ()); generator.writeEndObject (); }}

Vi vil nu anvende serializer til den klasse, der vil blive serialiseret:

@JsonSerialize (ved hjælp af = DistanceSerializer.class) offentlig enum TypeEnum {...}

Hvilket resulterer i:

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

4. Deserialisering af JSON til Enum

Lad os først definere en By klasse, der har en Afstand medlem:

offentlig klasse By {privat Afstand afstand; ...}

Dernæst diskuterer vi de forskellige måder at deserialisere en JSON-streng til en Enum.

4.1. Standardadfærd

Som standard bruger Jackson navnet Enum til at deserialisere fra JSON.

For eksempel vil det deserialisere JSON:

{"distance": "KILOMETER"}

Til en Afstand. KILOMETER objekt:

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

4.2. Ved brug af @JsonValue

Vi har lært at bruge @JsonValue at serieisere Enums. Vi kan også bruge den samme kommentar til deserialisering. Dette er muligt, fordi Enum-værdier er konstanter.

Lad os først bruge @JsonValue med en af ​​getter-metoderne - getMeters ():

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

Nu er returværdien af getMeters () metode repræsenterer Enum-objekterne. Når du deserialiserer prøven JSON:

{"distance": "0,0254"}

Jackson vil kigge efter Enum-objektet, der har en getMeters () returværdi på 0,0254. I dette tilfælde er genstanden Afstand.Tommer:

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

4.3. Ved brug af @JsonProperty

Det @JsonProperty annotation bruges i optællingsforekomster:

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

Ved at bruge denne kommentar, vi beder simpelthen Jackson om at kortlægge værdien af @JsonProperty til objektet, der er kommenteret med denne værdi.

Som et resultat af ovenstående erklæring er eksemplet JSON-streng:

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

Vil blive kortlagt til Afstand. KILOMETER objekt:

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

4.4. Ved brug af @JsonCreator

Jackson påkalder metoder, der er kommenteret med @JsonCreator for at få en forekomst af den lukkende klasse.

Overvej JSON-repræsentationen:

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

Lad os nu definere forValues ​​() fabriksmetode med @JsonCreator kommentar:

public enum Distance {@JsonCreator public static Distance forValues ​​(@JsonProperty ("unit") Strengenhed, @JsonProperty ("meter") dobbelt meter) {for (Distance distance: Distance.values ​​()) {if (distance.unit. er lig med (enhed) && Double.compare (distance.meters, meter) == 0) {returafstand; }} returner null; } ...}

Bemærk brugen af @JsonProperty kommentar til at binde JSON-felterne med metodeargumenterne.

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

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

4.5. Brug af en brugerdefineret Deserializer

En brugerdefineret deserializer kan bruges, hvis ingen af ​​de beskrevne teknikker er tilgængelige. For eksempel har vi muligvis ingen adgang til Enum-kildekoden, eller vi bruger muligvis en ældre Jackson-version, der ikke understøtter en eller flere af de hidtil dækkede kommentarer.

I henhold til vores brugerdefinerede deserialiseringsartikel starter vi med at oprette deserialiseringsklassen for at deserialisere JSON, der er givet i det foregående afsnit:

offentlig klasse CustomEnumDeserializer udvider StdDeserializer {@Override public Distance deserialize (JsonParser jsonParser, DeserializationContext ctxt) kaster IOException, JsonProcessingException {JsonNode node = jsonParser.getCodec (). readTree (;son) Strengenhed = node.get ("enhed"). Som tekst (); dobbelt meter = node.get ("meter"). asDouble (); for (Distance distance: Distance.values ​​()) {if (distance.getUnit (). er lig med (enhed) && Double.compare (distance.getMeters (), meter) == 0) {returafstand; }} returner null; }} 

Dernæst bruger vi @JsonDeserialize kommentar på Enum for at specificere vores brugerdefinerede deserializer:

@JsonDeserialize (ved hjælp af = CustomEnumDeserializer.class) offentlig enum Afstand {...}

Og vores resultat er:

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

5. Konklusion

Denne artikel illustrerede, hvordan man får bedre kontrol over serialiserings- og deserialiseringsprocesser og formater af Java Enums.

Implementeringen af ​​alle disse eksempler og kodestykker findes på GitHub.


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