Een dynamisch JSON-object in kaart brengen met Jackson

1. Inleiding

Het werken met vooraf gedefinieerde JSON-datastructuren met Jackson is eenvoudig. Soms moeten we echter omgaan met dynamiek JSON-objecten, die onbekende eigenschappen hebben.

In deze korte tutorial zullen we meerdere manieren zien om dynamische JSON-objecten toe te wijzen aan Java-klassen.

Merk op dat we bij alle tests aannemen dat we een veld hebben objectMapper van het type com.fasterxml.jackson.databind.ObjectMapper.

2. Met behulp van JsonNode

Stel dat we productspecificaties in een webshop willen verwerken. Alle producten hebben een aantal gemeenschappelijke eigenschappen, maar er zijn er andere, die afhankelijk zijn van het type product.

We willen bijvoorbeeld de hoogte-breedteverhouding van het scherm van een mobiele telefoon weten, maar deze eigenschap heeft niet veel zin voor een schoen.

De datastructuur ziet er als volgt uit:

{"name": "Pear yPhone 72", "category": "cellphone", "details": {"displayAspectRatio": "97: 3", "audioConnector": "none"}}

We slaan de dynamische eigenschappen op in het details voorwerp.

We kunnen de gemeenschappelijke eigenschappen in kaart brengen met de volgende Java-klasse:

klasse Product {Stringnaam; String categorie; // standaard getters en setters}

Bovendien hebben we een passende weergave nodig voor de details voorwerp. Bijvoorbeeld, com.fasterxml.jackson.databind.JsonNode kan omgaan met dynamische sleutels.

Om het te gebruiken, moeten we het als een veld toevoegen aan ons Product klasse:

class Product {// gemeenschappelijke velden JsonNode-details; // standaard getters en setters}

Ten slotte controleren we of het werkt:

String json = ""; Product product = objectMapper.readValue (json, Product.class); assertThat (product.getName ()). isEqualTo ("Pear yPhone 72"); assertThat (product.getDetails (). get ("audioConnector"). asText ()). isEqualTo ("none");

We hebben echter een probleem met deze oplossing. Onze klas is afhankelijk van de Jackson-bibliotheek aangezien we een JsonNode veld.

3. Met behulp van Kaart

We kunnen dit probleem oplossen door gebruik te maken van java.util.Map voor de details veld. Om precies te zijn, we moeten gebruiken Kaart.

Al het andere kan hetzelfde blijven:

klasse Product {// gemeenschappelijke velden Kaartdetails; // standaard getters en setters}

En dan kunnen we het verifiëren met een test:

String json = ""; Product product = objectMapper.readValue (json, Product.class); assertThat (product.getName ()). isEqualTo ("Pear yPhone 72"); assertThat (product.getDetails (). get ("audioConnector")). isEqualTo ("none");

4. Met behulp van @RTLnieuws

De voorgaande oplossingen zijn goed als een object alleen dynamische eigenschappen bevat. Maar soms hebben we vaste en dynamische eigenschappen gemengd in één JSON-object.

Het is bijvoorbeeld mogelijk dat we onze productweergave moeten afvlakken:

{"name": "Pear yPhone 72", "category": "cellphone", "displayAspectRatio": "97: 3", "audioConnector": "none"}

We kunnen een structuur als deze behandelen als een dynamisch object. Helaas betekent dit dat we geen gemeenschappelijke eigenschappen kunnen definiëren - we moeten ze ook dynamisch behandelen.

Als alternatief kunnen we gebruiken @RTLnieuws om een ​​methode te markeren voor het omgaan met aanvullende, onbekende eigenschappen. Zo'n methode zou twee argumenten moeten accepteren: de naam en waarde van de eigenschap:

class Product {// gemeenschappelijke velden Kaartdetails = nieuwe LinkedHashMap (); @JsonAnySetter void setDetail (String key, Object value) {details.put (key, value); } // standaard getters en setters}

Merk op dat we het details object te vermijden NullPointerExceptions.

Omdat we de dynamische eigenschappen opslaan in een Kaart, kunnen we het op dezelfde manier gebruiken als voorheen:

String json = ""; Product product = objectMapper.readValue (json, Product.class); assertThat (product.getName ()). isEqualTo ("Pear yPhone 72"); assertThat (product.getDetails (). get ("audioConnector")). isEqualTo ("none");

5. Een aangepaste deserializer maken

In de meeste gevallen werken deze oplossingen prima. Soms hebben we echter veel meer controle nodig. We kunnen bijvoorbeeld deserialisatie-informatie over onze JSON-objecten in een database opslaan.

We kunnen die situaties aanpakken met een aangepaste deserializer. Omdat het een complex onderwerp is, behandelen we het in een ander artikel, Aan de slag met aangepaste deserialisatie in Jackson.

6. Conclusie

In dit artikel hebben we meerdere manieren gezien om dynamische JSON-objecten met Jackson af te handelen.

Zoals gewoonlijk zijn de voorbeelden beschikbaar op GitHub.