Introduktion til Jackson ObjectMapper

1. Oversigt

Denne vejledning fokuserer på at forstå Jackson ObjectMapper klasse og hvordan man serieliserer Java-objekter til JSON og deserialiserer JSON-streng til Java-objekter.

For at forstå mere om Jackson-biblioteket generelt er Jackson Tutorial et godt sted at starte.

2. Afhængigheder

Lad os først tilføje følgende afhængigheder til pom.xml:

 com.fasterxml.jackson.core jackson-databind 2.11.1 

Denne afhængighed tilføjer også følgende biblioteker til klassestien:

  1. jackson-annoteringer
  2. jackson-core

Brug altid de nyeste versioner fra Maven centrale lager til jackson-databind.

3. Læsning og skrivning ved hjælp af ObjectMapper

Lad os starte med de grundlæggende læse- og skriveoperationer.

Det enkle readValue API af ObjectMapper er et godt indgangspunkt. Vi kan bruge det til at analysere eller deserialisere JSON-indhold til et Java-objekt.

Også på skrivesiden, vi kan bruge skrivVærdi API til at serieisere ethvert Java-objekt som JSON-output.

Vi bruger følgende Bil klasse med to felter som objekt til serie- eller deserialisering i hele denne artikel:

offentlig klasse bil {privat strengfarve; privat streng type; // standard getters setters}

3.1. Java-objekt til JSON

Lad os se et første eksempel på serialisering af et Java-objekt til JSON ved hjælp af skrivVærdi metode til ObjectMapper klasse:

ObjectMapper objectMapper = ny ObjectMapper (); Bilbil = ny bil ("gul", "renault"); objectMapper.writeValue (ny fil ("target / car.json"), bil); 

Outputtet af ovenstående i filen vil være:

{"color": "gul", "type": "renault"} 

Metoderne writeValueAsString og writeValueAsBytes af ObjectMapper klasse genererer en JSON fra et Java-objekt og returnerer den genererede JSON som en streng eller som en byte-array:

String carAsString = objectMapper.writeValueAsString (bil); 

3.2. JSON til Java-objekt

Nedenfor er et simpelt eksempel på konvertering af en JSON-streng til et Java-objekt ved hjælp af ObjectMapper klasse:

String json = "{\" color \ ": \" Black \ ", \" type \ ": \" BMW \ "}"; Bilbil = objectMapper.readValue (json, Car.class); 

Det readValue () funktion accepterer også andre former for input, såsom en fil, der indeholder JSON-streng:

Car car = objectMapper.readValue (ny fil ("src / test / resources / json_car.json"), Car.class);

eller en URL:

Car car = objectMapper.readValue (ny URL ("fil: src / test / resources / json_car.json"), Car.class);

3.3. JSON til Jackson JsonNode

Alternativt kan en JSON parses til en JsonNode objekt og bruges til at hente data fra en bestemt node:

String json = "{\" color \ ": \" Black \ ", \" type \ ": \" FIAT \ "}"; JsonNode jsonNode = objectMapper.readTree (json); Strengfarve = jsonNode.get ("farve"). AsText (); // Output: farve -> Sort 

3.4. Oprettelse af en Java-liste ud fra en JSON Array-streng

Vi kan analysere en JSON i form af en matrix i en Java-objektliste ved hjælp af en TypeReference:

String jsonCarArray = "[{\" farve \ ": \" Sort \ ", \" type \ ": \" BMW \ "}, {\" farve \ ": \" Rød \ ", \" type \ ": \"FIAT\" }]"; List listCar = objectMapper.readValue (jsonCarArray, ny TypeReference(){}); 

3.5. Oprettelse af Java-kort fra JSON-streng

På samme måde kan vi analysere en JSON i en Java Kort:

String json = "{\" color \ ": \" Black \ ", \" type \ ": \" BMW \ "}"; Kortkort = objectMapper.readValue (json, ny TypeReference(){}); 

4. Avancerede funktioner

En af de største styrker ved Jackson-biblioteket er den meget tilpasselige serie- og deserialiseringsproces.

I dette afsnit gennemgår vi nogle avancerede funktioner, hvor input eller output JSON-respons kan være forskelligt fra det objekt, der genererer eller forbruger svaret.

4.1. Konfiguration af Serialization eller Deserialization Feature

Under konvertering af JSON-objekter til Java-klasser, hvis JSON-strengen har nogle nye felter, vil standardprocessen resultere i en undtagelse:

String jsonString = "{\" color \ ": \" Black \ ", \" type \ ": \" Fiat \ ", \" year \ ": \" 1970 \ "}"; 

JSON-strengen i ovenstående eksempel i standard-parseringsprocessen til Java-objektet for Klassebil vil resultere i UnrecognisedPropertyException undtagelse.

Gennem konfigurere metode, kan vi udvide standardprocessen til at ignorere de nye felter:

objectMapper.configure (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); Car car = objectMapper.readValue (jsonString, Car.class); JsonNode jsonNodeRoot = objectMapper.readTree (jsonString); JsonNode jsonNodeYear = jsonNodeRoot.get ("år"); Strengår = jsonNodeYear.asText (); 

Endnu en anden mulighed er baseret på FAIL_ON_NULL_FOR_PRIMITIVES, som definerer, om nul værdier for primitive værdier er tilladt:

objectMapper.configure (DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false); 

Tilsvarende FAIL_ON_NUMBERS_FOR_ENUM kontrollerer, om enumværdier tillades at serie- / deserialiseres som tal:

objectMapper.configure (DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);

Du kan finde den omfattende liste over serialiserings- og deserialiseringsfunktioner på det officielle websted.

4.2. Oprettelse af brugerdefineret Serializer eller Deserializer

Et andet væsentligt træk ved ObjectMapper klasse er evnen til at registrere en tilpasset serializer og deserializer.

Brugerdefinerede serialiseringer og deserialiseringer er meget nyttige i situationer, hvor input- eller output-JSON-svaret har en anden struktur end Java-klassen, som det skal serieiseres eller deserialiseres til.

Nedenfor er et eksempel på en brugerdefineret JSON serializer:

public class CustomCarSerializer udvider StdSerializer {public CustomCarSerializer () {this (null); } offentlig CustomCarSerializer (klasse t) {super (t); } @Override public void serialize (Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) {jsonGenerator.writeStartObject (); jsonGenerator.writeStringField ("car_brand", car.getType ()); jsonGenerator.writeEndObject (); }} 

Denne brugerdefinerede serializer kan påberåbes som denne:

ObjectMapper-kortlægger = ny ObjectMapper (); SimpleModule-modul = nyt SimpleModule ("CustomCarSerializer", ny version (1, 0, 0, null, null, null)); module.addSerializer (Car.class, ny CustomCarSerializer ()); mapper.registerModule (modul); Bilbil = ny bil ("gul", "renault"); String carJson = mapper.writeValueAsString (bil); 

Her er hvad Bil ligner (som JSON-output) på klientsiden:

var carJson = {"car_brand": "renault"} 

Og her er et eksempel på en brugerdefineret JSON deserializer:

offentlig klasse CustomCarDeserializer udvider StdDeserializer {offentlig CustomCarDeserializer () {dette (null); } offentlig CustomCarDeserializer (klasse vc) {super (vc); } @ Override public Car deserialize (JsonParser parser, DeserializationContext deserializer) {Car car = new Car (); ObjectCodec codec = parser.getCodec (); JsonNode-node = codec.readTree (parser); // prøv fangstblok JsonNode colorNode = node.get ("farve"); Strengfarve = colorNode.asText (); car.setColor (farve); returbil; }} 

Denne brugerdefinerede deserializer kan påberåbes på denne måde:

String json = "{\" color \ ": \" Black \ ", \" type \ ": \" BMW \ "}"; ObjectMapper-kortlægger = ny ObjectMapper (); SimpleModule-modul = nyt SimpleModule ("CustomCarDeserializer", ny version (1, 0, 0, null, null, null)); module.addDeserializer (Car.class, ny CustomCarDeserializer ()); mapper.registerModule (modul); Bilbil = mapper.readValue (json, Car.class); 

4.3. Håndtering af datoformater

Standard serialisering af java.util.Date producerer et tal, dvs. epoke-tidsstempel (antal millisekunder siden 1. januar 1970, UTC). Men dette er ikke meget menneskeligt læsbart og kræver yderligere konvertering for at blive vist i et menneskeligt læsbart format.

Lad os pakke ind Bil eksempel vi brugte så langt inde i Anmodning klasse med datoKøbt ejendom:

offentlig klasse Anmodning {privat bil bil; privat Dato datoKøbt; // standard getters setters} 

For at kontrollere strengformatet for en dato og indstille den til f.eks. åååå-MM-dd HH: mm a z, overvej følgende uddrag:

ObjectMapper objectMapper = ny ObjectMapper (); DateFormat df = ny SimpleDateFormat ("åååå-MM-dd HH: mm a z"); objectMapper.setDateFormat (df); String carAsString = objectMapper.writeValueAsString (anmodning); // output: {"car": {"color": "yellow", "type": "renault"}, "datePurchased": "2016-07-03 11:43 CEST"} 

For at lære mere om serialisering af datoer med Jackson, kan du læse vores mere detaljerede beskrivelse.

4.4. Håndtering af samlinger

En anden lille, men nyttig funktion tilgængelig via Deserialisering Funktion klasse er evnen til at generere den type samling, vi ønsker fra et JSON Array-svar.

For eksempel kan vi generere resultatet som en matrix:

String jsonCarArray = "[{\" farve \ ": \" Sort \ ", \" type \ ": \" BMW \ "}, {\" farve \ ": \" Rød \ ", \" type \ ": \"FIAT\" }]"; ObjectMapper objectMapper = ny ObjectMapper (); objectMapper.configure (DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, sandt); Bil [] biler = objectMapper.readValue (jsonCarArray, bil []. Klasse); // printbiler

Eller som en Liste:

String jsonCarArray = "[{\" farve \ ": \" Sort \ ", \" type \ ": \" BMW \ "}, {\" farve \ ": \" Rød \ ", \" type \ ": \"FIAT\" }]"; ObjectMapper objectMapper = ny ObjectMapper (); List listCar = objectMapper.readValue (jsonCarArray, ny TypeReference() {}); // printbiler

Flere oplysninger om håndtering af samlinger med Jackson er tilgængelige her.

5. Konklusion

Jackson er et solidt og modent JSON-serialiserings- / deserialiseringsbibliotek til Java. Det ObjectMapper API giver en ligetil måde at analysere og generere JSON-responsobjekter med stor fleksibilitet. Denne artikel diskuterede de vigtigste funktioner, der gør biblioteket så populært.

Kildekoden, der ledsager artiklen, kan findes på GitHub.