Jackson kivételek - problémák és megoldások
1. Áttekintés
Ebben az oktatóanyagban áttekintjük a leggyakoribb Jackson-kivételek - a JsonMappingException és UnrecognizedPropertyException.
Végül - röviden átbeszéljük Jacksont, hogy nincs ilyen módszerhiba.
2. “JsonMappingException: Nem lehet megépíteni a
2.1. A probléma
Először - vessünk egy pillantást a Jsonmappingexception: Can Construct példányára.
Ezt a kivételt akkor dobják meg, ha Jackson nem hozhat létre példányt az osztályból - ez akkor történik, ha az osztály van absztrakt vagy csak egy felület.
A következő példában - megpróbálunk deserializálni egy példányt az osztályból Állatkert amelynek van tulajdonsága állat val vel absztrakt típus Állat:
közosztályú állatkert {nyilvános állatállat; public Zoo () {}} absztrakt osztály Animal {public String name; public Animal () {}} osztály Cat meghosszabbítja az Animal {public int életét; nyilvános macska () {}}
Amikor megpróbálunk deszerializálni egy JSON-t Húr az állatkert-példányba dobja a „Jsonmappingexception: Nem lehet megépíteni az
@Test (várható = JsonMappingException.class) public void givenAbstractClass_whenDeserializing_thenException () dobja az IOException {String json = "{" animal ": {" name ":" csipkés "}}"; ObjectMapper mapper = új ObjectMapper (); mapper.reader (). forType (Zoo.class) .readValue (json); }
A teljes kivétel az:
com.fasterxml.jackson.databind.JsonMappingException: Nem lehet létrehozni az org.baeldung.jackson.exception példányát. Állat, probléma: az absztrakt típusokat vagy konkrét típusokhoz kell hozzárendelni, egyéni deserializátorral kell ellátni őket, vagy további típusú információkkal kell példázni a következő címen: [Forrás: {"animal": {"name": "csipkés"}}; sor: 1, oszlop: 2] (hivatkozási láncon keresztül: org.baeldung.jackson.exception.Zoo ["állat"]) itt: c.f.j.d.JsonMappingException.from (JsonMappingException.java:148)
2.2. Megoldások
Egy egyszerű feljegyzéssel megoldhatjuk a problémát - @JsonDeserialize az absztrakt osztályon:
@JsonDeserialize (as = Cat.class) absztrakt osztály Animal {...}
Ha az absztrakt osztálynak egynél több altípusa van, akkor fontolóra kell vennünk az altípusra vonatkozó információk beillesztését, amint az ebben a bejegyzésben látható: Öröklés Jacksonnal.
3. JsonMappingException: Nincs megfelelő kivitelező
3.1. A probléma
Most - nézzük meg a Jsonmappingexception: Nincs megfelelő konstrukciót típusra talált.
Ezt a kivételt akkor dobják meg, ha Jackson nem fér hozzá a kivitelezőhöz.
A következő példában - osztály Felhasználó nincs alapértelmezett konstruktora:
public class Felhasználó {public int id; public String név; public Felhasználó (int id, String név) {this.id = id; ez.név = név; }}
Amikor megpróbálunk deszerializálni egy JSON karakterláncot a felhasználó számára, a „Jsonmappingexception: Nem található megfelelő konstruktor található” felirat dobódik - ahogy a következő példában:
@Test (várható = JsonMappingException.class) public void givenNoDefaultConstructor_whenDeserializing_thenException () dobja az IOException {String json = "{" id ": 1," name ":" John "}"; ObjectMapper mapper = új ObjectMapper (); mapper.reader (). forType (Felhasználó.osztály) .readValue (json); }
A teljes kivétel az:
com.fasterxml.jackson.databind.JsonMappingException: Nem található megfelelő kivitelező az [egyszerű típus, osztály org.baeldung.jackson.exception.User] típushoz: nem lehet példányosítani a JSON objektumból (a típusinformáció hozzáadása / engedélyezése szükséges?) a [ Forrás: {"id": 1, "name": "John"}; sor: 1, oszlop: 2] itt: c.f.j.d. JsonMappingException.from (JsonMappingException.java:148)
3.2. A megoldás
A probléma megoldásához egyszerűen adjon hozzá egy alapértelmezett konstruktort a következő példa szerint:
public class Felhasználó {public int id; public String név; public User () {super (); } public Felhasználó (int id, String name) {this.id = id; ez.név = név; }}
Most, amikor deszerializálódunk - a folyamat remekül fog működni:
@Test public void givenDefaultConstructor_whenDeserializing_thenCorrect () dobja az IOException {String json = "{" id ": 1," name ":" John "}"; ObjectMapper mapper = új ObjectMapper (); Felhasználói felhasználó = mapper.reader () .forType (Felhasználó.osztály) .readValue (json); assertEquals ("John", felhasználónév); }
4. JsonMappingException: A gyökérnév nem felel meg a vártnak
4.1. A probléma
Következő - vessünk egy pillantást a Jsonmappingexception oldalra: A gyökérnév nem felel meg a vártnak
Ezt a kivételt akkor dobják meg, ha a JSON nem egyezik meg pontosan azzal, amit Jackson keres; például a fő JSON-t a következő példa szerint lehet becsomagolni:
@Test (várható = JsonMappingException.class) public void givenWrappedJsonString_whenDeserializing_thenException () dobja az IOException {String json = "{" user ": {" id ": 1," name ":" John "}}"; ObjectMapper mapper = új ObjectMapper (); mapper.enable (DeserializationFeature.UNWRAP_ROOT_VALUE); mapper.reader (). forType (Felhasználó.osztály) .readValue (json); }
A teljes kivétel az:
com.fasterxml.jackson.databind.JsonMappingException: A 'user' gyökérnév nem egyezik a várt ('User') névvel az [simple type, class org.baeldung.jackson.dtos.User] típusnál a [Source: {"user": {"id": 1, "név": "John"}}; sor: 1, oszlop: 2] itt: c.f.j.d. JsonMappingException.from (JsonMappingException.java:148)
4.2. A megoldás
Megoldhatjuk ezt a problémát az annotáció segítségével @JsonRootName - mint a következő példában:
@JsonRootName (value = "user") public class UserWithRoot {public int id; public String név; }
Amikor megpróbáljuk deserializálni a bebugyolált JSON-ot - ez helyesen működik:
@Test public void givenWrappedJsonStringAndConfigureClass_whenDeserializing_thenCorrect () dobja az IOException {String json = "{" user ": {" id ": 1," name ":" John "}}"; ObjectMapper mapper = új ObjectMapper (); mapper.enable (DeserializationFeature.UNWRAP_ROOT_VALUE); UserWithRoot user = mapper.reader () .forType (UserWithRoot.class) .readValue (json); assertEquals ("John", felhasználónév); }
5. JsonMappingException: Nem található Serializer az osztályhoz
5.1. A probléma
Most - vessünk egy pillantást a Jsonmappingexception: Nem található Serializer osztályra.
Ezt a kivételt akkor dobják meg, ha megpróbálja Sorosítson egy példányt, miközben a tulajdonságai és az összesítőik privátak.
A következő példában - megpróbálunk egy „UserWithPrivateFields“:
public class UserWithPrivateFields {int id; Karakterlánc neve; }
Amikor megpróbáljuk sorosítani aUserWithPrivateFields”- a„ Jsonmappingexception: Nem található sorosító az osztályhoz ”kivétel a következő példában szerepel:
@Test (várható = JsonMappingException.class) public void givenClassWithPrivateFields_whenSerializing_thenException () dobja az IOException {UserWithPrivateFields user = new UserWithPrivateFields (1, "John"); ObjectMapper mapper = új ObjectMapper (); mapper.writer (). writeValueAsString (felhasználó); }
A teljes kivétel:
com.fasterxml.jackson.databind.JsonMappingException: Nem található sorosító a (z) org.baeldung.jackson.exception.UserWithPrivateFields osztályhoz, és a BeanSerializer létrehozásához nem találtak tulajdonságokat (a kivétel elkerülése érdekében tiltsa le a SerializationFeature.FAIL_ON_EMPTY_fájlokat. failForEmpty (UnknownSerializer.java:59)
5.2. A megoldás
Megoldhatjuk ezt a problémát a ObjectMapper láthatóság - mint a következő példában:
@Test public void givenClassWithPrivateFields_whenConfigureSerializing_thenCorrect () dobja az IOException {UserWithPrivateFields felhasználó = new UserWithPrivateFields (1, "John"); ObjectMapper mapper = új ObjectMapper (); mapper.setVisibility (PropertyAccessor.FIELD, Visibility.ANY); Karakterlánc eredménye = mapper.writer (). WriteValueAsString (felhasználó); assertThat (eredmény, tartalmazzaString ("John")); }
Vagy az annotáció használatával @JsonAutoDetect - mint a következő példában:
@JsonAutoDetect (fieldVisibility = Visibility.ANY) public class UserWithPrivateFields {...}
Természetesen, ha van lehetőségünk módosítani az osztály forrását, akkor hozzáadhatunk gettert is Jackson számára.
6. JsonMappingException: Nem deserializálhatom a
6.1. A probléma
Következő - vessünk egy pillantást a Jsonmappingexception: Nem lehet deserializálni a.
Ezt a kivételt akkor dobják meg, ha rossz típust használnak miközben deserializált.
A következő példában - megpróbáljuk deserializálni a Lista nak,-nek Felhasználó:
@Test (várható = JsonMappingException.class) public void givenJsonOfArray_whenDeserializing_thenException () dobja JsonProcessingException, IOException {String json = "[{" id ": 1," name ":" John "}, {" id ": 2, :"Ádám"}]"; ObjectMapper mapper = új ObjectMapper (); mapper.reader (). forType (Felhasználó.osztály) .readValue (json); }
A teljes kivétel az:
com.fasterxml.jackson.databind.JsonMappingException: Nem lehet deserializálni az org.baeldung.jackson.dtos.User példányát a START_ARRAY tokenből a [Forrás: [{"id": 1, "név": "John"}, { "id": 2, "név": "Ádám"}]; sor: 1, oszlop: 1] itt: c.f.j.d. JsonMappingException.from (JsonMappingException.java:148)
6.2. A megoldás
Megoldhatjuk ezt a problémát a típus megváltoztatásával Felhasználó nak nek Lista - mint a következő példában:
@Test public void givenJsonOfArray_whenDeserializing_thenCorrect () dobja a JsonProcessingException, IOException {String json = "[{" id ": 1," name ":" John "}, {" id ": 2," name ":" Adam "}]" " ; ObjectMapper mapper = új ObjectMapper (); List users = mapper.reader () .forType (új TypeReference() {}) .readValue (json); assertEquals (2, users.size ()); }
7. UnrecognizedPropertyException
7.1. A probléma
Most - nézzük meg a UnrecognizedPropertyException.
Ezt a kivételt akkor dobják meg, ha van ismeretlen tulajdonság a JSON-ban Húr, miközben deserializál.
A következő példában - megpróbálunk egy JSON karakterláncot deszerializálni extra tulajdonsággal “ellenőrzött“:
@Test (várható = UnrecognizedPropertyException.class) public void givenJsonStringWithExtra_whenDeserializing_thenException () dobja az IOException {String json = "{" id ": 1," név ":" John "," bejelölt ": igaz}"; ObjectMapper mapper = új ObjectMapper (); mapper.reader (). forType (Felhasználó.osztály) .readValue (json); }
A teljes kivétel az:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Ismeretlen mező "bejelölve" (class org.baeldung.jackson.dtos.User), nincs jelölve tudhatatlannak (2 ismert tulajdonság: "id", "név"]) a [ Forrás: {"id": 1, "név": "John", "bejelölt": igaz}; sor: 1, oszlop: 38] (hivatkozási láncon keresztül: org.baeldung.jackson.dtos.User ["bejelölve"]) a c.f.j.d.exc.UnrecognizedPropertyException.from (UnrecognizedPropertyException.java:51) címen
7.2. A megoldás
Megoldhatjuk ezt a problémát a ObjectMapper - mint a következő példában:
@Test public void givenJsonStringWithExtra_whenConfigureDeserializing_thenCorrect () dobja az IOException {String json = "{" id ": 1," name ":" John "," check ": true}"; ObjectMapper mapper = új ObjectMapper (); mapper.disable (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); Felhasználói felhasználó = mapper.reader (). ForType (Felhasználó.osztály) .readValue (json); assertEquals ("John", felhasználónév); }
Vagy használhatjuk az annotációt @JsonIgnoreProperties:
@JsonIgnoreProperties (ignoreUnknown = true) nyilvános osztály Felhasználó {...}
8. JsonParseException: Váratlan karakter (”” (39. kód))
8.1. A probléma
Következő - beszéljük meg JsonParseException: Váratlan karakter (”” (39-es kód)).
Ezt a kivételt akkor dobják meg, ha a deszerializálandó JSON karakterlánc egyetlen idézőjelet tartalmaz dupla idézőjelek helyett.
A következő példában - megpróbálunk deszerializálni egy idézőjeleket tartalmazó JSON karakterláncot:
@Test (várható = JsonParseException.class) public void givenStringWithSingleQuotes_whenDeserializing_thenException () dobja JsonProcessingException, IOException {String json = "{'id': 1, 'name': 'John'}"; ObjectMapper mapper = új ObjectMapper (); mapper.reader () .forType (Felhasználó.osztály) .readValue (json); }
A teljes kivétel az:
com.fasterxml.jackson.core.JsonParseException: Váratlan karakter ('' '(39-es kód)): kettős idézettel számított arra, hogy a mező nevét a [Forrás: {' id ': 1,' név ':' John '} mezőbe kezdi. ; sor: 1, oszlop: 3] a c.f.j.core.JsonParser._constructError (JsonParser.java:1419)
8.2. A megoldás
Megoldhatjuk ezt a ObjectMapper hogy egyetlen idézetet engedélyezzen:
@Test public void givenStringWithSingleQuotes_whenConfigureDeserializing_thenCorrect () dobja JsonProcessingException, IOException {String json = "{'id': 1, 'name': 'John'}"; JsonFactory gyár = új JsonFactory (); factory.enable (JsonParser.Feature.ALLOW_SINGLE_QUOTES); ObjectMapper mapper = új ObjectMapper (gyári); Felhasználói felhasználó = mapper.reader (). ForType (Felhasználó.osztály) .readValue (json); assertEquals ("John", felhasználónév); }
9. Jackson NoSuchMethodError
Végül - beszéljük meg gyorsan a Jackson „Nincs ilyen módszer” hibákat.
Mikor java.lang.NoSuchMethodError Kivételt dobnak, általában azért, mert az osztályterületén több (és inkompatibilis) Jackson edény verziója van.
A teljes kivétel az:
java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonParser.getValueAsString () Ljava / lang / String; itt: c.f.j.d.deser.std.StringDeserializer.deserialize (StringDeserializer.java:24)
10. Következtetés
Ebben a cikkben mélyen belemerültünk a leggyakoribb Jackson-problémák - kivételek és hibák, megvizsgálva az egyes lehetséges okokat és megoldásokat.
Mindezen példák és kódrészletek megvalósítása megtalálható a Githubon - ez egy Maven-alapú projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.