Mapiranje dinamičkog JSON objekta s Jacksonom
1. Uvod
Rad s unaprijed definiranim JSON-ovim strukturama podataka s Jacksonom je jednostavan. Međutim, ponekad se moramo nositi s dinamikom JSON objekti koji imaju nepoznata svojstva.
U ovom kratkom vodiču vidjet ćemo više načina mapiranja dinamičkih JSON objekata u Java klase.
Imajte na umu da u svim testovima pretpostavljamo da imamo polje objectMapper tipa com.fasterxml.jackson.databind.ObjectMapper.
2. Korištenje JsonNode
Recimo da želimo obraditi specifikacije proizvoda u web trgovini. Svi proizvodi imaju neka zajednička svojstva, ali postoje i druga koja ovise o vrsti proizvoda.
Na primjer, želimo znati omjer prikaza zaslona mobitela, ali ovo svojstvo nema puno smisla za cipelu.
Struktura podataka izgleda ovako:
{"name": "Pear yPhone 72", "category": "cellphone", "details": {"displayAspectRatio": "97: 3", "audioConnector": "none"}}
Dinamička svojstva pohranjujemo u pojedinosti objekt.
Uobičajena svojstva možemo mapirati sa sljedećom Java klasom:
class Product {Naziv niza; Kategorija žica; // standardni geteri i postavljači}
Povrh toga, trebamo odgovarajuće predstavljanje za pojedinosti objekt. Na primjer, com.fasterxml.jackson.databind.JsonNode može rukovati dinamičkim tipkama.
Da bismo ga koristili, moramo ga dodati kao polje našem Proizvod razred:
klasa Proizvod {// zajednička polja detalji JsonNode; // standardni geteri i postavljači}
Konačno, provjeravamo radi li:
Niz json = ""; Proizvod proizvoda = objectMapper.readValue (json, Product.class); assertThat (product.getName ()). isEqualTo ("Kruška yPhone 72"); assertThat (product.getDetails (). get ("audioConnector"). asText ()). isEqualTo ("none");
Međutim, imamo problem s ovim rješenjem. Naš razred ovisi o Jacksonovoj knjižnici jer imamo JsonNode polje.
3. Korištenje Karta
Ovaj problem možemo riješiti pomoću java.util.Map za pojedinosti polje. Točnije, moramo koristiti Karta.
Sve ostalo može ostati isto:
klasa Proizvod {// zajednička polja Detalji karte; // standardni geteri i postavljači}
A onda to možemo provjeriti testom:
Niz json = ""; Product product = objectMapper.readValue (json, Product.class); assertThat (product.getName ()). isEqualTo ("Kruška yPhone 72"); assertThat (product.getDetails (). get ("audioConnector")). isEqualTo ("none");
4. Korištenje @JsonAnySetter
Prethodna rješenja dobra su kada objekt sadrži samo dinamička svojstva. Međutim, ponekad imamo fiksna i dinamička svojstva pomiješana u jednom JSON objektu.
Na primjer, možda ćemo morati izravnati svoju zastupljenost proizvoda:
{"name": "Pear yPhone 72", "category": "cellphone", "displayAspectRatio": "97: 3", "audioConnector": "none"}
Ovakvu strukturu možemo tretirati kao dinamički objekt. Nažalost, to znači da ne možemo definirati uobičajena svojstva - moramo ih i dinamički tretirati.
Ili bismo mogli koristiti @JsonAnySetter za označavanje metode za rukovanje dodatnim, nepoznatim svojstvima. Takva metoda trebala bi prihvatiti dva argumenta: ime i vrijednost svojstva:
class Product {// uobičajena polja Detalji karte = new LinkedHashMap (); @JsonAnySetter void setDetail (ključ niza, vrijednost objekta) {details.put (ključ, vrijednost); } // standardni getteri i postavljači}
Imajte na umu da moramo instancirati pojedinosti objekt koji treba izbjegavati NullPointerExceptions.
Budući da dinamička svojstva pohranjujemo u Karta, možemo ga koristiti na isti način kao i prije:
Niz json = ""; Product product = objectMapper.readValue (json, Product.class); assertThat (product.getName ()). isEqualTo ("Kruška yPhone 72"); assertThat (product.getDetails (). get ("audioConnector")). isEqualTo ("none");
5. Izrada prilagođenog deserijalizatora
U većini slučajeva ova rješenja djeluju sasvim u redu. Međutim, ponekad nam treba puno više kontrole. Na primjer, podatke o deserijalizaciji o našim JSON objektima mogli bismo pohraniti u bazu podataka.
Te situacije možemo ciljati prilagođenim deserijalizatorom. Budući da je riječ o složenoj temi, obrađujemo je u drugom članku, počevši s prilagođenom deserijalizacijom u Jacksonu.
6. Zaključak
U ovom smo članku vidjeli više načina za rukovanje dinamičkim JSON objektima s Jacksonom.
Kao i obično, primjeri su dostupni na GitHubu.