Jacksonove výnimky - problémy a riešenia

1. Prehľad

V tomto návode si prejdeme najbežnejšie Jacksonove výnimky - the JsonMappingException a UnrecognizedPropertyException.

Na záver - krátko hovoríme o Jacksonovi, že nedochádza k takýmto chybám metód.

2. “JsonMappingException: Nie je možné vytvoriť inštanciu “

2.1. Problém

Po prvé - poďme sa pozrieť na výnimku Jsonmapping: Can not Construct Instance Of.

Táto výnimka je vyvolaná, ak Jackson nemôže vytvoriť inštanciu triedy - toto sa stane, ak je trieda abstraktné alebo je to len rozhranie.

V nasledujúcom príklade sa pokúsime deserializovať inštanciu z triedy Zoo ktorá má nehnuteľnosť zviera s abstraktné typu Zviera:

verejná trieda Zoo {verejné Zvieracie zviera; public Zoo () {}} abstraktná trieda Zviera {verejné Názov reťazca; public Animal () {}} trieda Cat rozširuje Animal {public int lives; public Cat () {}}

Keď sa pokúsime deserializovať súbor JSON String inštancii Zoo hodí „Výnimku Jsonmapping: Can Can Construct Instance Of“ ako v nasledujúcom príklade:

@Test (očakáva sa = JsonMappingException.class) public void givenAbstractClass_whenDeserializing_thenException () vyvolá IOException {String json = "{" animal ": {" name ":" lacy "}}"; ObjectMapper mapovač = nový ObjectMapper (); mapper.reader (). forType (Zoo.class) .readValue (json); }

The úplná výnimka je:

com.fasterxml.jackson.databind.JsonMappingException: Nie je možné vytvoriť inštanciu org.baeldung.jackson.exception. Zviera, problém: abstraktné typy musia byť namapované na konkrétne typy, majú vlastný deserializátor alebo musia byť inštancované s ďalšími informáciami o type na [Zdroj: {"animal": {"name": "lacy"}}; riadok: 1, stĺpec: 2] (prostredníctvom referenčného reťazca: org.baeldung.jackson.exception.Zoo ["zviera"]) na adrese c.f.j.d.JsonMappingException.from (JsonMappingException.java:148)

2.2. Riešenia

Problém môžeme vyriešiť jednoduchou anotáciou - @JsonDeserialize v abstraktnej triede:

@JsonDeserialize (as = Cat.class) abstraktná trieda Zviera {...}

Ak máme viac ako jeden podtyp abstraktnej triedy, mali by sme zvážiť zahrnutie informácií o podtype, ktoré sú uvedené v tomto príspevku: Dedenie s Jacksonom.

3. JsonMappingException: Žiadny vhodný konštruktor

3.1. Problém

Teraz - pozrime sa na spoločnú výnimku Jsonmapping: Žiadny vhodný konštruktor nájdené pre typ.

Táto výnimka je vyvolaná, ak Jackson nemá prístup ku konštruktorovi.

V nasledujúcom príklade - trieda Používateľ nemá predvoleného konštruktora:

public class User {public int id; verejné meno reťazca; public User (int id, String name) {this.id = id; this.name = meno; }}

Pri pokuse o deserializáciu reťazca JSON na používateľa sa vyvolá výnimka „Jsonmappingexception: Nenašiel sa žiadny vhodný konštruktor“ - ako v nasledujúcom príklade:

@Test (očakáva sa = JsonMappingException.class) public void givenNoDefaultConstructor_whenDeserializing_thenException () vyvolá IOException {String json = "{" id ": 1," name ":" John "}"; ObjectMapper mapovač = nový ObjectMapper (); mapper.reader (). forType (User.class) .readValue (json); }

The úplná výnimka je:

com.fasterxml.jackson.databind.JsonMappingException: Nenašiel sa žiadny vhodný konštruktor pre typ [jednoduchý typ, trieda org.baeldung.jackson.exception.User]: nemožno vytvoriť inštanciu z objektu JSON (je potrebné pridať / povoliť informácie o type?) na [ Zdroj: {"id": 1, "name": "John"}; riadok: 1, stĺpec: 2] na adrese c.f.j.d.JsonMappingException.from (JsonMappingException.java:148)

3.2. Riešenie

Ak chcete vyriešiť tento problém - stačí pridať predvolený konštruktor ako v nasledujúcom príklade:

public class User {public int id; verejné meno reťazca; public User () {super (); } public User (int id, String name) {this.id = id; this.name = meno; }}

Teraz, keď deserializujeme - proces bude fungovať celkom dobre:

@ Test public void givenDefaultConstructor_whenDeserializing_thenCorrect () vyvolá IOException {String json = "{" id ": 1," name ":" John "}"; ObjectMapper mapovač = nový ObjectMapper (); Používateľ user = mapper.reader () .forType (User.class) .readValue (json); assertEquals ("John", meno_uzivatela); }

4. JsonMappingException: Koreňový názov sa nezhoduje

4.1. Problém

Ďalej - poďme sa pozrieť na výnimku Jsonmapping: Očakávaný koreňový názov sa nezhoduje.

Táto výnimka je vyvolaná, ak súbor JSON sa nezhoduje presne s tým, čo Jackson hľadá; napríklad hlavný JSON môže byť zabalený ako v nasledujúcom príklade:

@Test (očakáva sa = JsonMappingException.class) public void givenWrappedJsonString_whenDeserializing_thenException () vyvolá IOException {String json = "{" user ": {" id ": 1," name ":" John "}}"; ObjectMapper mapovač = nový ObjectMapper (); mapper.enable (DeserializationFeature.UNWRAP_ROOT_VALUE); mapper.reader (). forType (User.class) .readValue (json); }

The úplná výnimka je:

com.fasterxml.jackson.databind.JsonMappingException: koreňový názov „user“ sa nezhoduje s očakávaním („User“) pre typ [jednoduchý typ, trieda org.baeldung.jackson.dtos.User] na adrese [Zdroj: {„používateľ“: {"id": 1, "name": "John"}}; riadok: 1, stĺpec: 2] na adrese c.f.j.d.JsonMappingException.from (JsonMappingException.java:148) 

4.2. Riešenie

Tento problém môžeme vyriešiť pomocou anotácie @JsonRootName - ako v nasledujúcom príklade:

@JsonRootName (hodnota = "užívateľ") verejná trieda UserWithRoot {verejné int id; verejné meno reťazca; }

Keď sa pokúsime deserializovať zabalený JSON - funguje to správne:

@Test public void givenWrappedJsonStringAndConfigureClass_whenDeserializing_thenCorrect () vyvolá IOException {String json = "{" user ": {" id ": 1," name ":" John "}}"; ObjectMapper mapovač = nový ObjectMapper (); mapper.enable (DeserializationFeature.UNWRAP_ROOT_VALUE); UserWithRoot user = mapper.reader () .forType (UserWithRoot.class) .readValue (json); assertEquals ("John", meno uzivatela); }

5. JsonMappingException: Pre triedu sa nenašiel žiadny serializátor

5.1. Problém

Teraz - poďme sa pozrieť na výnimku Jsonmapping: Pre triedu sa nenašiel žiadny serializátor.

Táto výnimka je vyvolaná, ak sa o to pokúsite serializovať inštanciu, zatiaľ čo jej vlastnosti a ich getre sú súkromné.

V nasledujúcom príklade sa pokúsime serializovať „UserWithPrivateFields“:

verejná trieda UserWithPrivateFields {int id; Názov reťazca; }

Keď sa pokúsime serializovať inštanciu „UserWithPrivateFields”- vyvolá sa výnimka„ Jsonmappingexception: No Classializer Found for Class “, ako v nasledujúcom príklade:

@Test (očakáva sa = JsonMappingException.class) public void givenClassWithPrivateFields_whenSerializing_thenException () hodí IOException {UserWithPrivateFields user = new UserWithPrivateFields (1, "John"); ObjectMapper mapovač = nový ObjectMapper (); mapper.writer (). writeValueAsString (užívateľ); }

Úplná výnimka je:

com.fasterxml.jackson.databind.JsonMappingException: Nenašiel sa žiadny serializátor pre triedu org.baeldung.jackson.exception.UserWithPrivateFields a nezistili sa žiadne vlastnosti potrebné na vytvorenie BeanSerializer (aby sa zabránilo výnimke, zakážte SerializationFeature.FAIL_ON_EMPTY_BEANS)) na adrese cfjdser.imer.pler.pler.imer failForEmpty (UnknownSerializer.java:59)

5.2. Riešenie

Tento problém môžeme vyriešiť konfiguráciou ObjectMapper viditeľnosť - ako v nasledujúcom príklade:

@ Test public void givenClassWithPrivateFields_whenConfigureSerializing_thenCorrect () vyvolá IOException {UserWithPrivateFields user = new UserWithPrivateFields (1, "John"); ObjectMapper mapovač = nový ObjectMapper (); mapper.setVisibility (PropertyAccessor.FIELD, Visibility.ANY); Výsledok reťazca = mapper.writer (). WriteValueAsString (užívateľ); assertThat (result, containsString ("John")); }

Alebo pomocou anotácie @JsonAutoDetect - ako v nasledujúcom príklade:

@JsonAutoDetect (fieldVisibility = Visibility.ANY) verejná trieda UserWithPrivateFields {...}

Samozrejme, ak máme možnosť upraviť zdroj triedy, môžeme pridať aj getre, ktoré Jackson použije.

6. JsonMappingException: Nie je možné deserializovať inštanciu z

6.1. Problém

Ďalej - pozrime sa na Jsonmappingexception: Can not Deserialize Instance Of.

Táto výnimka je vyvolaná, ak používa sa nesprávny typ pri deserializácii.

V nasledujúcom príklade - sa pokúšame deserializovať a Zoznam z Používateľ:

@Test (očakáva sa = JsonMappingException.class) public void givenJsonOfArray_whenDeserializing_thenException () vyvolá JsonProcessingException, IOException {String json = "[{" id ": 1," name ":" John "}, {" id ": 2," name " : "Adam"}] "; ObjectMapper mapovač = nový ObjectMapper (); mapper.reader (). forType (User.class) .readValue (json); }

The úplná výnimka je:

com.fasterxml.jackson.databind.JsonMappingException: Nie je možné deserializovať inštanciu org.baeldung.jackson.dtos.User out of START_ARRAY token at [Source: [{"id": 1, "name": "John"}, { "id": 2, "name": "Adam"}]; riadok: 1, stĺpec: 1] na adrese c.f.j.d.JsonMappingException.from (JsonMappingException.java:148)

6.2. Riešenie

Tento problém môžeme vyriešiť zmenou typu z Používateľ do Zoznam - ako v nasledujúcom príklade:

@Test public void givenJsonOfArray_whenDeserializing_thenCorrect () vyhodí JsonProcessingException, IOException {String json = "[{" id ": 1," name ":" John "}, {" id ": 2," name ":" Adam "}]" " ; ObjectMapper mapovač = nový ObjectMapper (); Zoznam používateľov = mapper.reader () .forType (nový TypeReference() {}) .readValue (json); assertEquals (2, users.size ()); }

7. UnrecognizedPropertyException

7.1. Problém

Teraz - pozrime sa na UnrecognizedPropertyException.

Táto výnimka je vyvolaná, ak existuje neznáma vlastnosť v JSON Reťazec počas deserializácie.

V nasledujúcom príklade - pokúsime sa deserializovať reťazec JSON s extra vlastnosťou “skontrolované“:

@Test (expect = UnrecognizedPropertyException.class) public void givenJsonStringWithExtra_whenDeserializing_thenException () vyvolá IOException {String json = "{" id ": 1," name ":" John "," checked ": true}"; ObjectMapper mapovač = nový ObjectMapper (); mapper.reader (). forType (User.class) .readValue (json); }

The úplná výnimka je:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Nerozpoznané pole „začiarknuté“ (trieda org.baeldung.jackson.dtos.User), neoznačené ako ignorovateľné (2 známe vlastnosti: „id“, „meno“]) na adrese [ Zdroj: {"id": 1, "name": "John", "checked": true}; riadok: 1, stĺpec: 38] (prostredníctvom referenčného reťazca: org.baeldung.jackson.dtos.User ["zaškrtnuté"]) na adrese c.f.j.d.exc.UnrecognizedPropertyException.from (UnrecognizedPropertyException.java:51)

7.2. Riešenie

Tento problém môžeme vyriešiť konfiguráciou ObjectMapper - ako v nasledujúcom príklade:

@ Test public void givenJsonStringWithExtra_whenConfigureDeserializing_thenCorrect () hodí IOException {String json = "{" id ": 1," name ":" John "," checked ": true}"; ObjectMapper mapovač = nový ObjectMapper (); mapper.disable (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); Používateľ user = mapper.reader (). ForType (User.class) .readValue (json); assertEquals ("John", meno_uzivatela); }

Alebo môžeme použiť anotáciu @JsonIgnoreProperties:

@JsonIgnoreProperties (ignoreUnknown = true) používateľ verejnej triedy {...}

8. JsonParseException: Neočakávaný znak (”(kód 39))

8.1. Problém

Ďalej - poďme diskutovať JsonParseException: Neočakávaný znak („“ (kód 39)).

Táto výnimka je vyvolaná, ak reťazec JSON, ktorý sa má deserializovať, obsahuje jednoduché úvodzovky namiesto dvojitých úvodzoviek.

V nasledujúcom príklade sa pokúsime deserializovať reťazec JSON obsahujúci jednoduché úvodzovky:

@Test (očakáva sa = JsonParseException.class) public void givenStringWithSingleQuotes_whenDeserializing_thenException () vyvolá JsonProcessingException, IOException {String json = "{'id': 1, 'name': 'John'}"; ObjectMapper mapovač = nový ObjectMapper (); mapper.reader () .forType (User.class) .readValue (json); }

The úplná výnimka je:

com.fasterxml.jackson.core.JsonParseException: Neočakávaný znak ('' (kód 39)): očakával dvojitú úvodzovku, aby začal názov poľa na [Zdroj: {'id': 1, 'name': 'John'} ; riadok: 1, stĺpec: 3] pri c.f.j.core.JsonParser._constructError (JsonParser.java:1419)

8.2. Riešenie

Môžeme to vyriešiť konfiguráciou ObjectMapper povoliť jednoduché úvodzovky:

@Test public void givenStringWithSingleQuotes_whenConfigureDeserializing_thenCorrect () vyvolá JsonProcessingException, IOException {String json = "{'id': 1, 'name': 'John'}"; JsonFactory factory = nový JsonFactory (); factory.enable (JsonParser.Feature.ALLOW_SINGLE_QUOTES); ObjectMapper mapovač = nový ObjectMapper (továreň); Používateľ user = mapper.reader (). ForType (User.class) .readValue (json); assertEquals ("John", meno uzivatela); }

9. Jackson NoSuchMethodError

Na záver - poďme rýchlo diskutovať o Jacksonových chybách „Žiadna takáto metóda“.

Kedy java.lang.NoSuchMethodError Vyvolá sa výnimka, je to zvyčajne preto, že na svojej triednej ceste máte viac (a nekompatibilných) verzií pohárov Jackson.

The úplná výnimka je:

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

10. Záver

V tomto článku sme sa podrobne ponorili najbežnejšie Jacksonove problémy - výnimky a chyby, pri pohľade na možné príčiny a na riešenie každej z nich.

Implementácia všetkých týchto príkladov a útržkov kódu nájdete na Githube - toto je projekt založený na Maven, takže by malo byť ľahké ho importovať a spustiť tak, ako je.


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