Kortlægning af et dynamisk JSON-objekt med Jackson

1. Introduktion

At arbejde med foruddefinerede JSON-datastrukturer med Jackson er ligetil. Men nogle gange er vi nødt til at håndtere dynamik JSON-objekter, som har ukendte egenskaber.

I denne korte vejledning ser vi flere måder at kortlægge dynamiske JSON-objekter i Java-klasser.

Bemærk, at vi i alle testene antager, at vi har et felt objectMapper af typen com.fasterxml.jackson.databind.ObjectMapper.

2. Brug JsonNode

Lad os sige, at vi vil behandle produktspecifikationer i en webshop. Alle produkter har nogle fælles egenskaber, men der er andre, der afhænger af produkttypen.

For eksempel vil vi vide billedformatet for displayet på en mobiltelefon, men denne egenskab giver ikke meget mening for en sko.

Datastrukturen ser sådan ud:

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

Vi gemmer de dynamiske egenskaber i detaljer objekt.

Vi kan kortlægge de fælles egenskaber med følgende Java-klasse:

klasse Produkt {Strengnavn; Strengkategori; // standard getters og setter}

Derudover har vi brug for en passende repræsentation for detaljer objekt. For eksempel, com.fasterxml.jackson.databind.JsonNode kan håndtere dynamiske nøgler.

For at bruge det skal vi tilføje det som et felt til vores Produkt klasse:

klasse Produkt {// fælles felter JsonNode detaljer; // standard getters og setter}

Endelig bekræfter vi, at det fungerer:

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

Vi har dog et problem med denne løsning. Vores klasse afhænger af Jackson-biblioteket, da vi har en JsonNode Mark.

3. Brug Kort

Vi kan løse dette problem ved hjælp af java.util.Kort til detaljer Mark. Mere præcist er vi nødt til at bruge Kort.

Alt andet kan forblive det samme:

klasse Produkt {// fælles felter Kortoplysninger; // standard getters og setter}

Og så kan vi verificere det med en test:

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

4. Brug @JsonAnySetter

De tidligere løsninger er gode, når et objekt kun indeholder dynamiske egenskaber. Men nogle gange har vi det faste og dynamiske egenskaber blandet i et enkelt JSON-objekt.

For eksempel kan det være nødvendigt at vi flader vores produktrepræsentation:

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

Vi kan behandle en struktur som denne som et dynamisk objekt. Desværre betyder det, at vi ikke kan definere fælles egenskaber - vi skal også behandle dem dynamisk.

Alternativt kunne vi bruge @JsonAnySetter for at markere en metode til håndtering af yderligere ukendte egenskaber. En sådan metode skal acceptere to argumenter: navn og værdi på ejendommen:

klasse Produkt {// fælles felter Kortoplysninger = ny LinkedHashMap (); @JsonAnySetter ugyldigt setDetail (strengnøgle, objektværdi) {details.put (nøgle, værdi); } // standard getters og setters}

Bemærk, at vi er nødt til at instantiere detaljer objekt at undgå NullPointerExceptions.

Da vi gemmer de dynamiske egenskaber i en Kort, kan vi bruge det på samme måde som før:

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

5. Oprettelse af en brugerdefineret deserializer

I de fleste tilfælde fungerer disse løsninger fint. Men nogle gange har vi brug for meget mere kontrol. For eksempel kunne vi gemme deserialiseringsoplysninger om vores JSON-objekter i en database.

Vi kan målrette mod disse situationer med en brugerdefineret deserializer. Da det er et komplekst emne, dækker vi det i en anden artikel, der kommer i gang med brugerdefineret deserialisering i Jackson.

6. Konklusion

I denne artikel så vi flere måder at håndtere dynamiske JSON-objekter med Jackson på.

Som sædvanligt er eksemplerne tilgængelige på GitHub.