Jacksonove iznimke - problemi i rješenja

1. Pregled

U ovom uputstvu ćemo prijeći najčešće Jackson iznimke - the JsonMappingException i NeprepoznatiPropertyException.

Napokon - ukratko ćemo razgovarati o Jacksonu bez takvih pogrešaka u metodi.

2. “JsonMappingException: Ne mogu konstruirati instancu ”

2.1. Problem

Prvo - pogledajmo Jsonmappingexception: Can't Construct Instance Of.

Ova se iznimka baca ako Jackson ne može stvoriti primjerak klase - to se događa ako je nastava sažetak ili je samo sučelje.

U sljedećem primjeru - pokušavamo deserializirati instancu iz klase Zoološki vrt koja ima svojstvo životinja s sažetak tip Životinja:

javni razred Zoo {javna Životinjska životinja; javni zoološki vrt () {}} sažetak klase životinja {javni naziv niza; javni Animal () {}} klasa Cat produžuje Animal {javni int život; javna mačka () {}}

Kada pokušamo deserializirati JSON Niz instanci Zoo-a baca “Jsonmappingexception: Can't Construct Instance Of” kao u sljedećem primjeru:

@Test (očekuje se = JsonMappingException.class) javna praznina givenAbstractClass_whenDeserializing_thenException () baca IOException {String json = "{" animal ": {" name ":" lacy "}}"; Mapa ObjectMapper = novi ObjectMapper (); mapper.reader (). forType (Zoo.class) .readValue (json); }

The puna iznimka je:

com.fasterxml.jackson.databind.JsonMappingException: Ne može se stvoriti instanca org.baeldung.jackson.exception.Animal, problem: apstraktni tipovi moraju biti mapirani u konkretne tipove, imati prilagođeni deserijalizator ili biti instancirani dodatnim informacijama o tipu [Izvor: {"životinja": {"ime": "čipkasto"}}; redak: 1, stupac: 2] (kroz referentni lanac: org.baeldung.jackson.exception.Zoo ["životinja"]) na c.f.j.d.JsonMappingException.from (JsonMappingException.java:148)

2.2. Rješenja

Problem možemo riješiti jednostavnom bilješkom - @JsonDeserialize na apstraktnom satu:

@JsonDeserialize (as = Cat.class) sažetak klase Životinja {...}

Ako imamo više od jedne podvrste apstraktne klase, trebali bismo razmotriti uključivanje informacija o podvrsti kao što je prikazano u ovom postu: Nasljeđivanje s Jacksonom.

3. JsonMappingException: Nema prikladnog konstruktora

3.1. Problem

Sada - pogledajmo uobičajeni Jsonmappingexception: Nema prikladnog konstruktora pronađeno za tip.

Ova se iznimka baca ako Jackson ne može pristupiti konstruktoru.

U sljedećem primjeru - klasa Korisnik nema zadani konstruktor:

javni razred korisnika {javni int id; naziv javnog niza; javni korisnik (int id, naziv niza) {this.id = id; this.name = ime; }}

Kada pokušavamo deserializirati JSON niz za korisnika, izbacuje se izuzetak "Jsonmappingexception: Nije pronađen odgovarajući konstruktor" - kao u sljedećem primjeru:

@Test (očekuje se = JsonMappingException.class) javna praznina givenNoDefaultConstructor_whenDeserializing_thenException () baca IOException {String json = "{" id ": 1," name ":" John "}"; Mapa ObjectMapper = novi ObjectMapper (); mapper.reader (). forType (User.class) .readValue (json); }

The puna iznimka je:

com.fasterxml.jackson.databind.JsonMappingException: Nije pronađen odgovarajući konstruktor za tip [jednostavan tip, klasa org.baeldung.jackson.exception.User]: nije moguće instanciranje iz JSON objekta (trebate dodati / omogućiti informacije o tipu?) na Izvor: {"id": 1, "name": "John"}; redak: 1, stupac: 2] na c.f.j.d.JsonMappingException.from (JsonMappingException.java:148)

3.2. Rješenje

Da biste riješili ovaj problem - samo dodajte zadani konstruktor kao u sljedećem primjeru:

javni razred korisnika {javni int id; naziv javnog niza; javni korisnik () {super (); } javni korisnik (int id, naziv niza) {this.id = id; this.name = ime; }}

Sada kada desezeriziramo - postupak će raditi sasvim u redu:

@Test javna praznina givenDefaultConstructor_whenDeserializing_thenCorrect () baca IOException {String json = "{" id ": 1," name ":" John "}"; Mapa ObjectMapper = novi ObjectMapper (); Korisnik korisnik = mapper.reader () .forType (User.class) .readValue (json); assertEquals ("John", korisničko ime); }

4. JsonMappingException: Ime korijena se ne podudara s očekivanim

4.1. Problem

Dalje - pogledajmo Jsonmappingexception: Ime korijena se ne podudara s očekivanim.

Ova se iznimka baca ako JSON se ne podudara točno s onim što Jackson traži; na primjer, glavni JSON mogao bi biti omotan kao u sljedećem primjeru:

@Test (očekuje se = JsonMappingException.class) javna praznina givenWrappedJsonString_whenDeserializing_thenException () baca IOException {String json = "{" user ": {" id ": 1," name ":" John "}}"; Mapa ObjectMapper = novi ObjectMapper (); mapper.enable (DeserializationFeature.UNWRAP_ROOT_VALUE); mapper.reader (). forType (User.class) .readValue (json); }

The puna iznimka je:

com.fasterxml.jackson.databind.JsonMappingException: Ime korijena 'user' ne podudara se s očekivanim ('User') za tip [simple type, class org.baeldung.jackson.dtos.User] na [Source: {"user": {"id": 1, "name": "Ivan"}}; redak: 1, stupac: 2] na c.f.j.d.JsonMappingException.from (JsonMappingException.java:148) 

4.2. Rješenje

Ovaj problem možemo riješiti pomoću bilješke @JsonRootName - kao u sljedećem primjeru:

@JsonRootName (value = "user") javna klasa UserWithRoot {javni int id; naziv javnog niza; }

Kada pokušamo deserializirati zamotani JSON - to ispravno radi:

@Test javna praznina givenWrappedJsonStringAndConfigureClass_whenDeserializing_thenCorrect () baca IOException {String json = "{" user ": {" id ": 1," name ":" John "}}"; Mapa ObjectMapper = novi ObjectMapper (); mapper.enable (DeserializationFeature.UNWRAP_ROOT_VALUE); UserWithRoot user = mapper.reader () .forType (UserWithRoot.class) .readValue (json); assertEquals ("John", korisničko ime); }

5. JsonMappingException: Nije pronađen serijalizator za klasu

5.1. Problem

Sada - pogledajmo Jsonmappingexception: Nije pronađen serilizator za klasu.

Ova se iznimka baca ako pokušate serializirajte instancu dok su njena svojstva i njihovi dohvatači privatni.

U sljedećem primjeru - pokušavamo serializirati "UserWithPrivateFields“:

javna klasa UserWithPrivateFields {int id; Naziv niza; }

Kada pokušamo serializirati instancu „UserWithPrivateFields"- dodana je iznimka" Jsonmappingexception: Nije pronađen serilizator za klasu "kao u sljedećem primjeru:

@Test (očekuje se = JsonMappingException.class) javna praznina givenClassWithPrivateFields_whenSerializing_thenException () baca IOException {UserWithPrivateFields user = new UserWithPrivateFields (1, "John"); Mapa ObjectMapper = novi ObjectMapper (); mapper.writer (). writeValueAsString (korisnik); }

Potpuna iznimka je:

com.fasterxml.jackson.databind.JsonMappingException: Nije pronađen serializator za klasu org.baeldung.jackson.exception.UserWithPrivateFields i nisu otkrivena svojstva za stvaranje BeanSerializer-a (da biste izbjegli izuzeće, onemogućite SerializationFeature.FAIL_ON_EMPTY_BEANSUERBEANSERP. failForEmpty (UnknownSerializer.java:59)

5.2. Rješenje

Taj problem možemo riješiti konfiguriranjem datoteke ObjectMapper vidljivost - kao u sljedećem primjeru:

@Test javna praznina givenClassWithPrivateFields_whenConfigureSerializing_thenCorrect () baca IOException {UserWithPrivateFields user = new UserWithPrivateFields (1, "John"); Mapa ObjectMapper = novi ObjectMapper (); mapper.setVisibility (PropertyAccessor.FIELD, Visibility.ANY); Rezultat niza = mapper.writer (). WriteValueAsString (korisnik); assertThat (rezultat, sadržiString ("Ivan")); }

Ili pomoću bilješke @JsonAutoDetect - kao u sljedećem primjeru:

@JsonAutoDetect (fieldVisibility = Visibility.ANY) javna klasa UserWithPrivateFields {...}

Naravno, ako imamo mogućnost modificiranja izvora klase, možemo dodati i gettere koje će Jackson koristiti.

6. JsonMappingException: Ne mogu deserijalizirati instancu

6.1. Problem

Dalje - pogledajmo Jsonmappingexception: Nije moguće deserijalizirati instancu.

Ova se iznimka baca ako koristi se pogrešan tip dok se deserializira.

U sljedećem primjeru - pokušavamo deserializirati a Popis od Korisnik:

@Test (očekuje se = JsonMappingException.class) javna praznina givenJsonOfArray_whenDeserializing_thenException () baca JsonProcessingException, IOException {String json = "[{" id ": 1," name ":" John "}, {" id ": 2" id ": 2" :"Adam"}]"; Mapa ObjectMapper = novi ObjectMapper (); mapper.reader (). forType (User.class) .readValue (json); }

The puna iznimka je:

com.fasterxml.jackson.databind.JsonMappingException: Nije moguće deserializirati instancu org.baeldung.jackson.dtos.Korisnik iz START_ARRAY tokena na [Izvor: [{"id": 1, "name": "John"}, { "id": 2, "name": "Adam"}]; redak: 1, stupac: 1] na c.f.j.d.JsonMappingException.from (JsonMappingException.java:148)

6.2. Rješenje

Taj problem možemo riješiti promjenom tipa iz Korisnik do Popis - kao u sljedećem primjeru:

@Test public void givenJsonOfArray_whenDeserializing_thenCorrect () baca JsonProcessingException, IOException {String json = "[{" id ": 1," name ":" John "}, {" id ": 2," name ":" Adam "}]" " ; Mapa ObjectMapper = novi ObjectMapper (); Popis korisnika = mapper.reader () .forType (novi TypeReference() {}) .readValue (json); assertEquals (2, users.size ()); }

7. NeprepoznatiPropertyException

7.1. Problem

Sad - da vidimo NeprepoznatiPropertyException.

Ova se iznimka baca ako postoji nepoznato svojstvo u JSON-u String tijekom deserializacije.

U sljedećem primjeru - pokušavamo deserializirati JSON niz s dodatnim svojstvom “provjereno“:

@Test (očekuje se = NeprepoznatoPropertyException.class) javna praznina givenJsonStringWithExtra_whenDeserializing_thenException () baca IOException {String json = "{" id ": 1," name ":" John "," checked ": true}"; Mapa ObjectMapper = novi ObjectMapper (); mapper.reader (). forType (User.class) .readValue (json); }

The puna iznimka je:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Neprepoznato polje "provjereno" (klasa org.baeldung.jackson.dtos.User), nije označeno kao zanemarivo (2 poznata svojstva: "id", "name"]) na [ Izvor: {"id": 1, "name": "John", "check": true}; redak: 1, stupac: 38] (kroz referentni lanac: org.baeldung.jackson.dtos.User ["provjereno"]) na c.f.j.d.exc.UnrecognizedPropertyException.from (UnrecognizedPropertyException.java:51)

7.2. Rješenje

Taj problem možemo riješiti konfiguriranjem datoteke ObjectMapper - kao u sljedećem primjeru:

@Test javna praznina givenJsonStringWithExtra_whenConfigureDeserializing_thenCorrect () baca IOException {String json = "{" id ": 1," name ":" John "," checked ": true}"; Mapa ObjectMapper = novi ObjectMapper (); mapper.disable (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); Korisnik korisnik = mapper.reader (). ForType (User.class) .readValue (json); assertEquals ("John", korisničko ime); }

Ili se možemo poslužiti napomenom @JsonIgnoreProperties:

@JsonIgnoreProperties (ignoreUnknown = true) korisnik javne klase {...}

8. JsonParseException: Neočekivani znak ("'(kod 39))

8.1. Problem

Dalje - razgovarajmo JsonParseException: Neočekivani znak (”'(kod 39)).

Ova se iznimka baca ako JSON-ov niz koji će se deserijalizirati sadrži pojedinačne navodnike umjesto dvostrukih navodnika.

U sljedećem primjeru - pokušavamo deserializirati JSON niz koji sadrži pojedinačne navodnike:

@Test (očekuje se = JsonParseException.class) javna praznina givenStringWithSingleQuotes_whenDeserializing_thenException () baca JsonProcessingException, IOException {String json = "{'id': 1, 'name': 'John'}"; Mapa ObjectMapper = novi ObjectMapper (); mapper.reader () .forType (User.class) .readValue (json); }

The puna iznimka je:

com.fasterxml.jackson.core.JsonParseException: Neočekivani znak ('' '(kod 39)): očekivao je dvostruki navodnik za početak imena polja na [Izvor: {' id ': 1,' name ':' John '} ; redak: 1, stupac: 3] na c.f.j.core.JsonParser._constructError (JsonParser.java:1419)

8.2. Rješenje

To možemo riješiti konfiguriranjem ObjectMapper dopustiti pojedinačne citate:

@Test javna praznina givenStringWithSingleQuotes_whenConfigureDeserializing_thenCorrect () baca JsonProcessingException, IOException {String json = "{'id': 1, 'name': 'John'}"; Tvornica JsonFactory = nova JsonFactory (); factory.enable (JsonParser.Feature.ALLOW_SINGLE_QUOTES); ObjectMapper mapper = novi ObjectMapper (tvornički); Korisnik korisnik = mapper.reader (). ForType (User.class) .readValue (json); assertEquals ("John", korisničko ime); }

9. Jackson NoSuchMethodError

Napokon - razgovarajmo brzo o Jacksonovim pogreškama "Nema takve metode".

Kada java.lang.NoSuchMethodError Iznimka se izbacuje, to je obično zato što na putu do razreda imate više (i nekompatibilnih) verzija Jackson staklenki.

The puna iznimka je:

java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonParser.getValueAsString () Ljava / lang / String; na c.f.j.d.deser.std.StringDeserializer.deserialize (StringDeserializer.java:24)

10. Zaključak

U ovom smo članku duboko zaronili najčešći Jacksonovi problemi - iznimke i pogreške, gledajući potencijalne uzroke i rješenja za svaki od njih.

Implementacija svih ovih primjera i isječaka koda može se naći na Githubu - ovo je projekt zasnovan na Mavenu, pa bi ga trebalo biti lako uvesti i pokrenuti kakav jest.


$config[zx-auto] not found$config[zx-overlay] not found