Jackson Undtagelser - Problemer og løsninger

1. Oversigt

I denne vejledning går vi over de mest almindelige Jackson-undtagelser - det JsonMappingException og UnrecognisedPropertyException.

Endelig - vi vil kort diskutere Jackson ingen sådanne metodefejl.

2. “JsonMappingException: Kan ikke konstruere forekomsten af ​​”

2.1. Problemet

Først - lad os tage et kig på Jsonmappingexception: Can not Construct Instance Of.

Denne undtagelse kastes, hvis Jackson kan ikke oprette en forekomst af klassen - dette sker, hvis klassen er det abstrakt eller det er bare en interface.

I det følgende eksempel prøver vi at deserialisere en forekomst fra klassen Zoo som har en ejendom dyr med abstrakt type Dyr:

offentlig klasse Zoo {offentligt dyr; public Zoo () {}} abstrakt klasse Animal {public String name; public Animal () {}} klasse Cat udvider Animal {public int lives; offentlig kat () {}}

Når vi prøver at deserialisere en JSON Snor til Zoo-instans kaster det “Jsonmappingexception: Can not Construct Instance Of” som i følgende eksempel:

@Test (forventet = JsonMappingException.class) offentlig ugyldighed givenAbstractClass_whenDeserializing_thenException () kaster IOException {String json = "{" animal ": {" name ":" lacy "}}"; ObjectMapper-kortlægger = ny ObjectMapper (); mapper.reader (). forType (Zoo.class) .readValue (json); }

Det fuld undtagelse er:

com.fasterxml.jackson.databind.JsonMappingException: Kan ikke konstruere forekomst af org.baeldung.jackson.exception.Animal, problem: abstrakte typer skal enten kortlægges til konkrete typer, har brugerdefineret deserializer eller instantieres med yderligere typeoplysninger på [Kilde: {"animal": {"name": "lacy"}}; linje: 1, kolonne: 2] (gennem referencekæde: org.baeldung.jackson.exception.Zoo ["animal"]) på c.f.j.d.JsonMappingException.from (JsonMappingException.java:148)

2.2. Løsninger

Vi kan løse problemet med en simpel kommentar - @JsonDeserialize på den abstrakte klasse:

@JsonDeserialize (som = Cat.class) abstrakt klasse Animal {...}

Hvis vi har mere end en undertype af den abstrakte klasse, bør vi overveje at inkludere subtypeoplysninger som vist i dette indlæg: Arv med Jackson.

3. JsonMappingException: Ingen egnede konstruktører

3.1. Problemet

Lad os nu se på den almindelige Jsonmappingexception: Ingen egnet konstruktør fundet for type.

Denne undtagelse kastes, hvis Jackson har ikke adgang til konstruktøren.

I det følgende eksempel - klasse Bruger har ikke en standardkonstruktør:

public class User {public int id; offentligt strengnavn; offentlig bruger (int id, strengnavn) {this.id = id; dette.navn = navn; }}

Når vi forsøger at deserialisere en JSON-streng til bruger, kastes en undtagelse "Jsonmappingexception: No Suitable Constructor found" - som i følgende eksempel:

@Test (forventet = JsonMappingException.class) offentlig ugyldighed givenNoDefaultConstructor_whenDeserializing_thenException () kaster IOException {String json = "{" id ": 1," name ":" John "}"; ObjectMapper-kortlægger = ny ObjectMapper (); mapper.reader (). forType (User.class) .readValue (json); }

Det fuld undtagelse er:

com.fasterxml.jackson.databind.JsonMappingException: Ingen passende konstruktør fundet til type [enkel type, klasse org.baeldung.jackson.exception.User]: kan ikke instantiere fra JSON-objekt (har brug for at tilføje / aktivere typeoplysninger?) på [ Kilde: {"id": 1, "name": "John"}; linje: 1, kolonne: 2] på c.f.j.d.JsonMappingException.from (JsonMappingException.java:148)

3.2. Løsningen

For at løse dette problem - tilføj bare en standardkonstruktør som i følgende eksempel:

public class User {public int id; offentligt strengnavn; offentlig bruger () {super (); } offentlig bruger (int id, strengnavn) {this.id = id; dette.navn = navn; }}

Nu når vi deserialiserer - processen fungerer fint:

@Test offentlig ugyldighed givenDefaultConstructor_whenDeserializing_thenCorrect () kaster IOException {String json = "{" id ": 1," name ":" John "}"; ObjectMapper-kortlægger = ny ObjectMapper (); Brugerbruger = mapper.reader () .forType (User.class) .readValue (json); assertEquals ("John", bruger.navn); }

4. JsonMappingException: Rodnavn stemmer ikke overens forventet

4.1. Problemet

Dernæst - lad os se på Jsonmappingexception: Root Name matcher ikke forventet.

Denne undtagelse kastes, hvis JSON matcher ikke nøjagtigt, hvad Jackson leder efter; for eksempel kunne hoved-JSON pakkes ind som i følgende eksempel:

@Test (forventet = JsonMappingException.class) offentlig ugyldighed givenWrappedJsonString_whenDeserializing_thenException () kaster IOException {String json = "{" bruger ": {" id ": 1," navn ":" John "}}"; ObjectMapper-kortlægger = ny ObjectMapper (); mapper.enable (DeserializationFeature.UNWRAP_ROOT_VALUE); mapper.reader (). forType (User.class) .readValue (json); }

Det fuld undtagelse er:

com.fasterxml.jackson.databind.JsonMappingException: rodnavnet 'bruger' matcher ikke forventet ('bruger') for typen [enkel type, klasse org.baeldung.jackson.dtos.User] på [Kilde: {"bruger": {"id": 1, "name": "John"}}; linje: 1, kolonne: 2] på c.f.j.d.JsonMappingException.from (JsonMappingException.java:148) 

4.2. Løsningen

Vi kan løse dette problem ved hjælp af kommentaren @JsonRootName - som i følgende eksempel:

@JsonRootName (værdi = "bruger") offentlig klasse UserWithRoot {public int id; offentligt strengnavn; }

Når vi forsøger at deserialisere den indpakkede JSON - fungerer det korrekt:

@Test offentlig ugyldighed givenWrappedJsonStringAndConfigureClass_whenDeserializing_thenCorrect () kaster IOException {String json = "{" bruger ": {" id ": 1," name ":" John "}}"; ObjectMapper-kortlægger = ny ObjectMapper (); mapper.enable (DeserializationFeature.UNWRAP_ROOT_VALUE); UserWithRoot-bruger = mapper.reader (). ForType (UserWithRoot.class) .readValue (json); assertEquals ("John", bruger.navn); }

5. JsonMappingException: Ingen Serializer fundet til klasse

5.1. Problemet

Lad os nu se på Jsonmappingexception: Ingen serializer fundet til klasse.

Denne undtagelse kastes, hvis du prøver serialisere en forekomst, mens dens egenskaber og deres getters er private.

I det følgende eksempel - vi forsøger at serieisere en “UserWithPrivateFields“:

offentlig klasse UserWithPrivateFields {int id; Strengnavn; }

Når vi forsøger at serieisere en forekomst af “UserWithPrivateFields”- en undtagelse“ Jsonmappingexception: No Serializer Found for Class ”kastes som i følgende eksempel:

@Test (forventet = JsonMappingException.class) offentlig ugyldighed givenClassWithPrivateFields_whenSerializing_thenException () kaster IOException {UserWithPrivateFields bruger = ny UserWithPrivateFields (1, "John"); ObjectMapper-kortlægger = ny ObjectMapper (); mapper.writer (). writeValueAsString (bruger); }

Den fulde undtagelse er:

com.fasterxml.jackson.databind.JsonMappingException: Ingen serializer fundet til klasse org.baeldung.jackson.exception.UserWithPrivateFields og ingen egenskaber opdaget til at oprette BeanSerializer (for at undgå undtagelse skal du deaktivere SerializationFeature.FAIL_ON_EMPTY_BEANS)) ved cfjdser.Simplizer. failForEmpty (UnknownSerializer.java:59)

5.2. Løsningen

Vi kan løse dette problem ved at konfigurere ObjectMapper synlighed - som i følgende eksempel:

@Test offentlig ugyldighed givenClassWithPrivateFields_whenConfigureSerializing_thenCorrect () kaster IOException {UserWithPrivateFields bruger = ny UserWithPrivateFields (1, "John"); ObjectMapper-kortlægger = ny ObjectMapper (); mapper.setVisibility (PropertyAccessor.FIELD, Visibility.ANY); Strengresultat = mapper.writer (). WriteValueAsString (bruger); assertThat (resultat, indeholderString ("John")); }

Eller ved hjælp af kommentaren @JsonAutoDetect - som i følgende eksempel:

@JsonAutoDetect (fieldVisibility = Visibility.ANY) offentlig klasse UserWithPrivateFields {...}

Selvfølgelig, hvis vi har mulighed for at ændre klassens kilde, kan vi også tilføje i getters, som Jackson kan bruge.

6. JsonMappingException: Kan ikke deserialisere forekomsten af

6.1. Problemet

Dernæst - lad os se på Jsonmappingexception: Can not Deserialize Instance Of.

Denne undtagelse kastes, hvis den forkerte type bruges mens deserialisering.

I det følgende eksempel prøver vi at deserialisere en Liste af Bruger:

@Test (forventet = JsonMappingException.class) offentlig ugyldighed givetJsonOfArray_whenDeserializing_thenException () kaster JsonProcessingException, IOException {String json = "[{" id ": 1," name ":" John "}, {" id ": 2," name " : "Adam"}] "; ObjectMapper-kortlægger = ny ObjectMapper (); mapper.reader (). forType (User.class) .readValue (json); }

Det fuld undtagelse er:

com.fasterxml.jackson.databind.JsonMappingException: Kan ikke deserialisere forekomst af org.baeldung.jackson.dtos.User ud af START_ARRAY-token ved [Kilde: [{"id": 1, "name": "John"}, { "id": 2, "name": "Adam"}]; linje: 1, kolonne: 1] på c.f.j.d.JsonMappingException.from (JsonMappingException.java:148)

6.2. Løsningen

Vi kan løse dette problem ved at ændre typen fra Bruger til Liste - som i følgende eksempel:

@Test offentligt ugyldigt givetJsonOfArray_whenDeserializing_thenCorrect () kaster JsonProcessingException, IOException {String json = "[{" id ": 1," name ":" John "}, {" id ": 2," name ":" Adam "}]" ; ObjectMapper-kortlægger = ny ObjectMapper (); Liste brugere = mapper.reader () .forType (ny TypeReference() {}) .readValue (json); assertEquals (2, users.size ()); }

7. UnrecognisedPropertyException

7.1. Problemet

Lad os nu se UnrecognisedPropertyException.

Denne undtagelse kastes, hvis der er en ukendt ejendom i JSON Streng under deserialisering.

I det følgende eksempel - forsøger vi at deserialisere en JSON-streng med ekstra egenskab “afkrydset“:

@Test (forventet = UnrecognizedPropertyException.class) offentlig ugyldighed givenJsonStringWithExtra_whenDeserializing_thenException () kaster IOException {String json = "{" id ": 1," name ":" John "," kontrolleret ": sand}"; ObjectMapper-kortlægger = ny ObjectMapper (); mapper.reader (). forType (User.class) .readValue (json); }

Det fuld undtagelse er:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Ikke-genkendt felt "markeret" (klasse org.baeldung.jackson.dtos.User), ikke markeret som uvidende (2 kendte egenskaber: "id", "name"]) ved [ Kilde: {"id": 1, "name": "John", "markeret": true}; linje: 1, kolonne: 38] (gennem referencekæde: org.baeldung.jackson.dtos.User ["markeret"]) ved c.f.j.d.exc.UnrecognizedPropertyException.from (UnrecognizedPropertyException.java:51)

7.2. Løsningen

Vi kan løse dette problem ved at konfigurere ObjectMapper - som i følgende eksempel:

@Test offentlig ugyldighed givetJsonStringWithExtra_whenConfigureDeserializing_thenCorrect () kaster IOException {String json = "{" id ": 1," name ":" John "," checked ": true}"; ObjectMapper-kortlægger = ny ObjectMapper (); mapper.disable (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); Brugerbruger = mapper.reader (). ForType (User.class) .readValue (json); assertEquals ("John", bruger.navn); }

Eller vi kan bruge kommentaren @JsonIgnoreProperties:

@JsonIgnoreProperties (ignoreUnknown = true) bruger i offentlig klasse {...}

8. JsonParseException: Uventet tegn (”'(kode 39))

8.1. Problemet

Næste - lad os diskutere JsonParseException: Uventet tegn (”'(kode 39)).

Denne undtagelse kastes, hvis JSON-strengen, der skal deserialiseres, indeholder enkelt anførselstegn i stedet for dobbelt tilbud.

I det følgende eksempel - forsøger vi at deserialisere en JSON-streng, der indeholder enkelt anførselstegn:

@Test (forventet = JsonParseException.class) offentlig ugyldighed givenStringWithSingleQuotes_whenDeserializing_thenException () kaster JsonProcessingException, IOException {String json = "{'id': 1, 'name': 'John'}"; ObjectMapper-kortlægger = ny ObjectMapper (); mapper.reader () .forType (User.class) .readValue (json); }

Det fuld undtagelse er:

com.fasterxml.jackson.core.JsonParseException: Uventet tegn ('' '(kode 39)): forventede, at dobbelt citat skulle starte feltnavn ved [Kilde: {' id ': 1,' name ':' John '} ; linje: 1, kolonne: 3] ved c.f.j.core.JsonParser._constructError (JsonParser.java:1419)

8.2. Løsningen

Vi kan løse dette ved at konfigurere ObjectMapper at tillade enkelt tilbud:

@Test offentlig ugyldighed givenStringWithSingleQuotes_whenConfigureDeserializing_thenCorrect () kaster JsonProcessingException, IOException {String json = "{'id': 1, 'name': 'John'}"; JsonFactory fabrik = ny JsonFactory (); factory.enable (JsonParser.Feature.ALLOW_SINGLE_QUOTES); ObjectMapper mapper = ny ObjectMapper (fabrik); Brugerbruger = mapper.reader (). ForType (User.class) .readValue (json); assertEquals ("John", bruger.navn); }

9. Jackson NoSuchMethodError

Endelig - lad os hurtigt diskutere Jackson "Ingen sådan metode" -fejl.

Hvornår java.lang.NoSuchMethodError Undtagelse kastes, det skyldes normalt, at du har flere (og inkompatible) versioner af Jackson-krukker på din klassesti.

Det fuld undtagelse er:

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

10. Konklusion

I denne artikel dykkede vi dybt ind de mest almindelige Jackson-problemer - undtagelser og fejl, ser på de potentielle årsager og løsningerne for hver enkelt.

Implementeringen af ​​alle disse eksempler og kodestykker kan findes på Github - dette er et Maven-baseret projekt, så det skal være let at importere og køre som det er.


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