Inleiding tot de Jackson ObjectMapper

1. Overzicht

Deze tutorial richt zich op het begrijpen van de Jackson ObjectMapper class en hoe Java-objecten in JSON te serialiseren en JSON-tekenreeks in Java-objecten te deserialiseren.

Om meer te weten over de Jackson-bibliotheek in het algemeen, is de Jackson Tutorial een goede plek om te beginnen.

2. Afhankelijkheden

Laten we eerst de volgende afhankelijkheden toevoegen aan het pom.xml:

 com.fasterxml.jackson.core jackson-databind 2.11.1 

Deze afhankelijkheid voegt ook tijdelijk de volgende bibliotheken toe aan het klassenpad:

  1. jackson-annotaties
  2. jackson-core

Gebruik altijd de laatste versies uit de centrale opslagplaats van Maven voor jackson-databind.

3. Lezen en schrijven met ObjectMapper

Laten we beginnen met de basis lees- en schrijfbewerkingen.

Het simpele readValue API van de ObjectMapper is een goed instappunt. We kunnen het gebruiken om JSON-inhoud in een Java-object te parseren of te deserialiseren.

Ook aan de schrijfkant, we kunnen de writeValue API om elk Java-object te serialiseren als JSON-uitvoer.

We zullen het volgende gebruiken Auto klasse met twee velden als het object dat in dit artikel moet worden geserialiseerd of gedeserialiseerd:

openbare klasse Auto {privé String kleur; privé String-type; // standaard getters setters}

3.1. Java-object naar JSON

Laten we een eerste voorbeeld bekijken van het serialiseren van een Java-object naar JSON met behulp van de writeValue methode van de ObjectMapper klasse:

ObjectMapper objectMapper = nieuwe ObjectMapper (); Auto auto = nieuwe auto ("geel", "renault"); objectMapper.writeValue (nieuw bestand ("target / car.json"), auto); 

De uitvoer van het bovenstaande in het bestand zal zijn:

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

De methodes writeValueAsString en writeValueAsBytes van ObjectMapper class genereert een JSON van een Java-object en retourneert de gegenereerde JSON als een string of als een byte-array:

String carAsString = objectMapper.writeValueAsString (auto); 

3.2. JSON naar Java-object

Hieronder ziet u een eenvoudig voorbeeld van het converteren van een JSON-string naar een Java-object met behulp van de ObjectMapper klasse:

String json = "{\" kleur \ ": \" Zwart \ ", \" type \ ": \" BMW \ "}"; Auto auto = objectMapper.readValue (json, Car.class); 

De readValue () functie accepteert ook andere vormen van invoer, zoals een bestand met JSON-string:

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

of een URL:

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

3.3. JSON naar Jackson JsonNode

Als alternatief kan een JSON worden geparseerd in een JsonNode object en wordt gebruikt om gegevens op te halen van een specifiek knooppunt:

String json = "{\" kleur \ ": \" Zwart \ ", \" type \ ": \" FIAT \ "}"; JsonNode jsonNode = objectMapper.readTree (json); String color = jsonNode.get ("color"). AsText (); // Uitvoer: kleur -> Zwart 

3.4. Een Java-lijst maken op basis van een JSON-array-string

We kunnen een JSON in de vorm van een array parseren in een Java-objectlijst met behulp van een TypeReference:

String jsonCarArray = "[{\" color \ ": \" Black \ ", \" type \ ": \" BMW \ "}, {\" color \ ": \" Red \ ", \" type \ ": \ "FIAT \"}] "; Lijst listCar = objectMapper.readValue (jsonCarArray, nieuw TypeReference(){}); 

3.5. Java-kaart maken op basis van JSON-tekenreeks

Evenzo kunnen we een JSON in een Java parseren Kaart:

String json = "{\" kleur \ ": \" Zwart \ ", \" type \ ": \" BMW \ "}"; Map map = objectMapper.readValue (json, nieuw TypeReference(){}); 

4. Geavanceerde functies

Een van de grootste sterke punten van de Jackson-bibliotheek is het in hoge mate aanpasbare serialisatie- en deserialiseringsproces.

In deze sectie bespreken we enkele geavanceerde functies waarbij de invoer- of uitvoer-JSON-reactie kan verschillen van het object dat de reactie genereert of verbruikt.

4.1. De serialisatiefunctie of de deserialisatiefunctie configureren

Bij het converteren van JSON-objecten naar Java-klassen, in het geval dat de JSON-reeks enkele nieuwe velden bevat, zal het standaardproces resulteren in een uitzondering:

String jsonString = "{\" kleur \ ": \" Zwart \ ", \" type \ ": \" Fiat \ ", \" jaar \ ": \" 1970 \ "}"; 

De JSON-tekenreeks in het bovenstaande voorbeeld in het standaard parseerproces naar het Java-object voor het Klasse auto zal resulteren in de UnrecognizedPropertyException uitzondering.

Door het configureren methode, kunnen we het standaardproces uitbreiden om de nieuwe velden te negeren:

objectMapper.configure (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); Auto auto = objectMapper.readValue (jsonString, Car.class); JsonNode jsonNodeRoot = objectMapper.readTree (jsonString); JsonNode jsonNodeYear = jsonNodeRoot.get ("jaar"); String jaar = jsonNodeYear.asText (); 

Nog een andere optie is gebaseerd op de FAIL_ON_NULL_FOR_PRIMITIVES, waarmee wordt bepaald of het nul waarden voor primitieve waarden zijn toegestaan:

objectMapper.configure (DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false); 

Evenzo FAIL_ON_NUMBERS_FOR_ENUM bepaalt of enum-waarden mogen worden geserialiseerd / gedeserialiseerd als getallen:

objectMapper.configure (DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);

U kunt de uitgebreide lijst met serialisatie- en deserialisatiefuncties vinden op de officiële site.

4.2. Een aangepaste serialisator of deserializer maken

Een ander essentieel kenmerk van de ObjectMapper class is de mogelijkheid om een ‚Äč‚Äčaangepaste serializer en deserializer te registreren.

Aangepaste serializers en deserializers zijn erg handig in situaties waarin de invoer- of uitvoer-JSON-respons anders is qua structuur dan de Java-klasse waarin deze moet worden geserialiseerd of gedeserialiseerd.

Hieronder ziet u een voorbeeld van een aangepaste JSON-serialisator:

openbare klasse CustomCarSerializer breidt StdSerializer uit {openbare CustomCarSerializer () {dit (null); } openbare CustomCarSerializer (Klasse t) {super (t); } @Override public void serialize (Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) {jsonGenerator.writeStartObject (); jsonGenerator.writeStringField ("auto_merk", car.getType ()); jsonGenerator.writeEndObject (); }} 

Deze aangepaste serialisator kan als volgt worden aangeroepen:

ObjectMapper-mapper = nieuwe ObjectMapper (); SimpleModule module = nieuwe SimpleModule ("CustomCarSerializer", nieuwe versie (1, 0, 0, null, null, null)); module.addSerializer (Car.class, nieuwe CustomCarSerializer ()); mapper.registerModule (module); Auto auto = nieuwe auto ("geel", "renault"); String carJson = mapper.writeValueAsString (auto); 

Hier is wat de Auto ziet eruit als (als JSON-uitvoer) aan de clientzijde:

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

En hier is een voorbeeld van een aangepaste JSON-deserializer:

openbare klasse CustomCarDeserializer breidt StdDeserializer uit {openbare CustomCarDeserializer () {dit (null); } openbare CustomCarDeserializer (Klasse vc) {super (vc); } @Override public Car deserialize (JsonParser parser, DeserializationContext deserializer) {Car car = new Car (); ObjectCodec codec = parser.getCodec (); JsonNode-knooppunt = codec.readTree (parser); // probeer blok JsonNode colorNode = node.get ("color") te vangen; String color = colorNode.asText (); car.setColor (kleur); auto inleveren; }} 

Deze aangepaste deserializer kan op deze manier worden aangeroepen:

String json = "{\" kleur \ ": \" Zwart \ ", \" type \ ": \" BMW \ "}"; ObjectMapper-mapper = nieuwe ObjectMapper (); SimpleModule module = nieuwe SimpleModule ("CustomCarDeserializer", nieuwe versie (1, 0, 0, null, null, null)); module.addDeserializer (Car.class, nieuwe CustomCarDeserializer ()); mapper.registerModule (module); Car car = mapper.readValue (json, Car.class); 

4.3. Omgaan met datumnotaties

De standaardserialisering van java.util.Date produceert een getal, d.w.z. epoch-tijdstempel (aantal milliseconden sinds 1 januari 1970, UTC). Maar dit is niet erg leesbaar voor mensen en vereist verdere conversie om te worden weergegeven in een voor mensen leesbaar formaat.

Laten we de Auto instantie die we tot nu toe hebben gebruikt in de Verzoek klasse met de Aankoopdatum eigendom:

openbare klasse Verzoek {privé auto auto; privé Datum datum Aankoop; // standaard getters setters} 

Om de tekenreeksnotatie van een datum te beheren en deze in te stellen op bijv. jjjj-MM-dd UU: mm a z, overweeg dan het volgende fragment:

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

Lees ons meer diepgaande artikel voor meer informatie over het serialiseren van datums met Jackson.

4.4. Omgaan met verzamelingen

Een andere kleine maar handige functie die beschikbaar is via de Deserialisatie Functie class is de mogelijkheid om het type collectie te genereren dat we willen op basis van een JSON Array-antwoord.

We kunnen het resultaat bijvoorbeeld als een array genereren:

String jsonCarArray = "[{\" color \ ": \" Black \ ", \" type \ ": \" BMW \ "}, {\" color \ ": \" Red \ ", \" type \ ": \ "FIAT \"}] "; ObjectMapper objectMapper = nieuwe ObjectMapper (); objectMapper.configure (DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, waar); Car [] cars = objectMapper.readValue (jsonCarArray, Car []. Class); // print auto's

Of als een Lijst:

String jsonCarArray = "[{\" color \ ": \" Black \ ", \" type \ ": \" BMW \ "}, {\" color \ ": \" Red \ ", \" type \ ": \ "FIAT \"}] "; ObjectMapper objectMapper = nieuwe ObjectMapper (); Lijst listCar = objectMapper.readValue (jsonCarArray, nieuw TypeReference() {}); // print auto's

Meer informatie over het omgaan met incasso's met Jackson is hier beschikbaar.

5. Conclusie

Jackson is een solide en volwassen JSON-serialisatie / deserialisatiebibliotheek voor Java. De ObjectMapper API biedt een eenvoudige manier om JSON-responsobjecten met veel flexibiliteit te parseren en te genereren. In dit artikel werden de belangrijkste functies besproken die de bibliotheek zo populair maken.

De broncode die bij het artikel hoort, is te vinden op GitHub.