杰克逊前

通过。开始使用Spring 5和Spring Boot 2学习春天课程:

>>查看课程

1.概述

在本教程中,我们将覆盖最常见的杰克逊例外- 这jsonmappingexception.UnrecognizedPropertyException

最后 - 我们将简要讨论杰克逊没有这样的方法错误。

进一步阅读:

杰克逊 - 自定义串行器

使用自定义串行程序使用jackson 2控制您的JSON输出。

杰克逊注释例子

杰克逊的核心基本上是一组注释 - 确保你理解这些井。

jackson中的自定义反序列化入门

使用Jackson将自定义JSON映射到任何java实体图,并完全控制反序列化过程。

2.“jsonmappingexception.:不能构造“

2.1。这个问题

首先 - 让我们来看看JSONMapppingException:无法构建实例。

如果杰克逊无法创建类的实例- 如果类是抽象的或者它只是一个接口

在以下示例中 - 我们尝试从课堂中解除实例动物园有一个财产动物抽象的类型动物:

公共类动物园{公共动物动物;公共动物园(){}}抽象类动物{公共字符串名称;公共动物(){}}类猫延伸{Public Int Lives;公共猫(){}}

当我们尝试将json反序列化时字符串到zoo实例它抛出“jsonmapppedException:无法构建实例”如下所示:

@Test(expected = JsonMappingException.class) public void givenAbstractClass_whenDeserializing_thenException() throws IOException {String json = "{"animal":{"name":"lacy"}}";objectapper mapper = new objectapper ();mapper.reader () .forType (Zoo.class) .readValue (json);}

完整的例外是:

com.fasterxml.jackson.databind.jsonMappingException:无法构建org.baeldung.jackson.exception.金宝搏188体育animal的实例,问题:抽象类型要么需要映射到具体类型,都有自定义Deserializer,或者以附加类型信息实例化[来源:{“动物”:{“名称”:“Lacy”}};线:1,列:2](通过参考链:org.baeldung.jackson.exception.zoo 金宝搏188体育[“动物”])在c.f.j.d.jsonmapptedException.from(jsonmappingexception.java:148)

2.2。解决方案

我们可以用简单的注释解决问题 -@JsonDeserialize关于抽象类:

@jsondeserialize(as = cat.class)抽象类动物{...}

如果我们有一个以上的抽象类的子类型,那么我们应该考虑包括子类型信息,如这篇文章所示:与杰克逊遗产

3.jsonmappingexception.:没有合适的构造器

3.1。这个问题

现在 - 让我们来看看常见的jsonmappingException:没有合适的构造函数找到了类型

如果Jackson无法访问构造函数

在以下示例中 - 类用户没有默认构造函数:

public class User {public int id;公共字符串名称;public User(int id, String name) {this。id = id;this.name =名称;}}

当我们尝试将JSON字符串反序列化为用户时,抛出“jsonmapppexception:未找到合适的构造函数” - 如下例所示:

@Test(expected = JsonMappingException.class) public void givenNoDefaultConstructor_whenDeserializing_thenException() throws IOException {String json = "{"id":1,"name":"John"}";objectapper mapper = new objectapper ();mapper.reader () .forType (User.class) .readValue (json);}

完整的例外是:

没有找到适合的构造函数类型[简单类型,类org. baeldun.jackson .exception.]金宝搏188体育在[Source: {"id":1,"name":"John"};jsonmappingexception .from(JsonMappingException.java:148)

3.2。解决方案

要解决此问题 - 只需在以下示例中添加默认构造函数:

public class User {public int id;公共字符串名称;公共用户(){super();公共用户(int id,字符串名称){this.id = id;this.name =名称;}}

现在,当我们反序列化时 - 该过程将正常工作:

@Test public void givendefaultconstructor_whendeserializing_thencright () throws IOException {String json = "{"id":1,"name":"John"}";objectapper mapper = new objectapper ();User User = mapper.reader() .forType(User.class).readValue(json);assertequal(“约翰”,user.name);}

4.jsonmappingexception.:根本不匹配预期

4.1。这个问题

下一步 - 让我们来看看JSONMapppingException:root名称不匹配。

如果json与杰克逊正在寻找什么;例如,主JSON可以像下面的例子那样包装:

@test(预期= jsonmappingexception.class)public voidedwoidedwrakejsonstring_whendeserialization_thenException()抛出IoException {String Json =“{”User“:{”ID“:1,”名称“:”John“}}”;objectapper mapper = new objectapper ();Mapper.Enable(deserializationFeature.unwrap_root_value);mapper.reader () .forType (User.class) .readValue (json);}

完整的例外是:

com.fasterxml.jackson.databind.jsonmappingException:根本名称'用户'不匹配预期的[简单类型,org.baeldung.jackson.dtos.user]在[source:{“user”:金宝搏188体育{“ID”:1,“名称”:“John”}};jsonmappingexception .from(JsonMappingException.java:148)

4.2。解决方案

我们可以使用注释来解决这个问题@JsonRootName- 如下例所示:

@JsonRootName(value = "user") public class UserWithRoot {public int id;公共字符串名称;}

当我们试图反序列化被包装的JSON时-它能正确工作:

@test public voidedwoidedwroidedjsonstringandconfigurecureclass_whendeserializing_thencorrect()抛出IoException {String Json =“{”用户“:{”ID“:1,”名称“:”John“}}”;objectapper mapper = new objectapper ();Mapper.Enable(deserializationFeature.unwrap_root_value);UserWithroot User = Mapper.Reader()。Fortype(UserWithroot.class).readValue(JSON);assertequal(“约翰”,user.name);}

5.jsonmappingexception.:没有找到班级的序列化器

5.1。这个问题

现在——让我们看一下Jsonmappingexception:没有为Class找到序列化器。

如果您尝试,则抛出此异常序列化一个实例,而它的属性及其getter是私有的

在以下示例中 - 我们尝试序列化a“UserWithPrivateFields.“:

公共类userwithprivatefields {int id;字符串名称;}

当我们试图序列化"UserWithPrivateFields.“ - 一个例外”jsonmapppexception:for类未找到erializer“,如下例所示:

@test(预期= jsonmappingexception.class)public voidedclasswithprivatefields_whenserializing_thenexception()reprows ioException {userwithprivatefields user = new userwithprivatefields(1,“John”);objectapper mapper = new objectapper ();Mapper.Writer()。writevalueastring(用户);}

完整的例外是:

com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.baeldung.jackson.exception.UserWithPrivateFields and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) at c.f.j.d.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:59)

5.2。解决方案

我们可以通过配置来解决这个问题objectmap可见性 - 如下例所示:

@test public voidedclasswithprivatefields_whenconfigureserialization_thencorrect()抛出ioException {userwithprivatefields user = new userwithprivatefields(1,“John”);objectapper mapper = new objectapper ();Mapper.SetVisibility(propertyAccessor.field,可见性。string结果= mapper.writer()。writevalueastring(用户);asserthat(结果,包含(“John”));}

或者使用注释@jsonautodetect.- 如下例所示:

@jsonautodetect(timevisibility =可见性.Any)公共类userwithprivatefields {...}

当然,如果我们有选择修改类的来源,我们还可以在杰克逊使用的getters中添加。

6.jsonmappingexception.:不能反序列化的实例

6.1。这个问题

接下来 - 让我们来看看JSONMapppedException:无法反序列化实例。

如果使用了错误的类型而反序列化。

在下面的例子中——我们正试图反序列化a列表用户:

@Test(expected = JsonMappingException.class) public void givenJsonOfArray_whenDeserializing_thenException() throws JsonProcessingException, IOException {String json = "[{"id":1,"name":"John"},{"id":2,"name":"Adam"}]";objectapper mapper = new objectapper ();mapper.reader () .forType (User.class) .readValue (json);}

完整的例外是:

com.fasterxml.jackson.databind.jsonmapptedException:无法将org.baeldung.jackson.dtos.user的实例脱金宝搏188体育离start_array令牌[源:[{“ID”:1,“名称”:“John”},{“ID”:2,“名称”:“adam”}];线:1,列:1]在c.f.j.d.jsonmapptexception.from(jsonmappingexception.java:148)

6.2。解决方案

我们可以通过改变类型来解决这个问题用户<用户列表>- 如下例所示:

@test public void getJsonofarray_whendeserializing_thencorrect()抛出jsonprocessingexception,ioException {String Json =“[{”ID“:1,”名称“:”John“},{”ID“:2,”名称“:”ADAM“}]”;objectapper mapper = new objectapper ();列表用户= mapper.reader()。Fortype(新的typeReference >(){}).readvalue(json);assertequals(2,users.size());}

7。UnrecognizedPropertyException

7.1。这个问题

现在 - 让我们看看UnrecognizedPropertyException

如果有的话,抛出这个例外JSON中的未知属性在反序列化字符串。

在下面的例子中-我们尝试反序列化一个JSON字符串与额外的属性"检查一下“:

@Test(expected = UnrecognizedPropertyException.class) public void givenjsonstringwiththextra_whendeserializing_thenexception () throws IOException {String json = "{"id":1,"name":"John", "checked":true}";objectapper mapper = new objectapper ();mapper.reader () .forType (User.class) .readValue (json);}

完整的例外是:

com.fasterxml.jackson.databind.exc.unrecognizedPropertyException:未被识别的字段“选中”(classed)(class org.baeldung.j金宝搏188体育ackson.dtos.user),未标记为无可用(2个已知属性:“ID”,“名称”“)在[来源:{“ID”:1,“名称”:“John”,“选中”:True};线:1,列:38](通过参考链:org.baeldung.jackson.dtos.user.user金宝搏188体育.stos.user.在c.f.j.d.exc.unrecognizedPropertyException.from(UnrecognizedPropertyException.java:51)

7.2。解决方案

我们可以通过配置来解决这个问题objectmap- 如下例所示:

@test public void给gensonstringwithextra_whenconfiguredeserializing_thencorrect()抛出IoException {String Json =“{”ID“:1,”名称“:”John“,”选中“:True}”;objectapper mapper = new objectapper ();mapper.able(deserializationfeature.fail_on_unknown_properties);用户user = mapper.reader()。fortype(user.class).readvalue(JSON);assertequal(“约翰”,user.name);}

或者我们可以使用注释@jsonignoreproperties.:

@JsonIgnoreProperties(ignoreUnknown = true) public class User{…}

8。JsonParseException:意外字符(" '(代码39))

8.1。这个问题

接下来 - 让我们讨论JsonParseException:意外字符(" '(代码39))

如果要反序列化的JSON字符串包含单引号而不是双引号。

在以下示例中 - 我们尝试将包含单引号的JSON字符串进行反序列化:

@test(预期= jsonparseexception.class)public voidedstringwithsinglequotes_whendeserializing_thenexception()抛出jsonprocessingexception,ioException {string json =“{'id':1,'name':'John'}”;objectapper mapper = new objectapper ();Mapper.Reader()。Fortype(user.Class).readValue(JSON);}

完整的例外是:

com.fasterxml.jackson.core.jsonparseexception:意外的字符('''(代码39)):预计在[源代码:{'id':1,'name':'John'};线:1,列:3]在c.f.j.core.jsonParser._ConstructError(JSONParser.java:1419)

8.2。解决方案

我们可以通过配置objectmap允许单引号:

@test public voidedstringwithsinglequotes_whenconfiguredeserialization_thencorrect()抛出jsonprocessingException,ioException {String Json =“{'ID':1,'name':'John'}”;jsonfactory factory = new jsonfactory();factory.able(jsonparser.feature.allow_single_quotes);ObjectMapper Mapper = New ObjectMapper(工厂);用户user = mapper.reader()。fortype(user.class).readvalue(JSON);assertequal(“约翰”,user.name);}

9.杰克逊NoSuchMethodError

最后,让我们快速讨论一下Jackson的“没有这样的方法”错误。

什么时候java.lang.NoSuchMethodError抛出异常,它通常是因为你的类路径上有多个(和不兼容)的杰克逊jars。

完整的例外是:

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

10.结论

在本文中,我们进行了深入研究最常见的Jackson问题——异常和错误,着眼于潜在的原因和每个问题的解决方案。

实现所有这些示例和代码片段可以找到GitHub.-这是一个基于maven的项目,所以它应该很容易导入和运行。

杰克逊底部

通过。开始使用Spring 5和Spring Boot 2学习春天课程:

>>查看课程
13注释
最老的
最新
内联反馈
查看所有评论
评论在本文上关闭!