Jackson with JSON: Unrecognized field, not marked as ignorable
我需要把某个JSON字符串转换成Java对象。我正在使用Jackson处理JSON。我无法控制输入JSON(我从Web服务读取)。这是我的输入json:
1 | {"wrapper":[{"id":"13","name":"Fred"}]} |
下面是一个简化的用例:
1 2 3 4 5 6 7 8 9 10 11 | private void tryReading() { String jsonStr ="{"wrapper"\:[{"id":"13","name":"Fred"}]}"; ObjectMapper mapper = new ObjectMapper(); Wrapper wrapper = null; try { wrapper = mapper.readValue(jsonStr , Wrapper.class); } catch (Exception e) { e.printStackTrace(); } System.out.println("wrapper =" + wrapper); } |
我的实体类是:
1 2 3 4 5 |
我的包装类基本上是一个容器对象,用于获取我的学生列表:
1 2 3 4 | public Class Wrapper { private List<Student> students; //getters & setters here } |
我一直收到这个错误,"wrapper"返回
1 2 3 4 5 6 | org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field"wrapper" (Class Wrapper), not marked as ignorable at [Source: java.io.StringReader@1198891; line: 1, column: 13] (through reference chain: Wrapper["wrapper"]) at org.codehaus.jackson.map.exc.UnrecognizedPropertyException .from(UnrecognizedPropertyException.java:53) |
您可以使用杰克逊的类级注释:
1 2 3 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties @JsonIgnoreProperties class { ... } |
它将忽略您在POJO中没有定义的所有属性。当您只是在JSON中查找一些属性,并且不想编写整个映射时非常有用。更多信息请访问杰克逊的网站。如果要忽略任何未声明的属性,则应编写:
1 | @JsonIgnoreProperties(ignoreUnknown = true) |
你可以使用
1 2 | ObjectMapper objectMapper = getObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
它将忽略所有未声明的属性。
第一个答案几乎是正确的,但是需要的是更改getter方法,而不是字段--字段是私有的(并且不是自动检测的);此外,如果两个字段都可见,getter比字段具有优先权。(也有方法使私有字段可见,但是如果您想要getter,则没有太多意义)
因此getter应该命名为
1 | @JsonProperty("wrapper") |
如果您喜欢getter方法名。
使用Jackson 2.6.0,这对我很有用:
1 2 3 | private static final ObjectMapper objectMapper = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
以及设置:
1 | @JsonIgnoreProperties(ignoreUnknown = true) |
它可以通过两种方式实现:
标记POJO以忽略未知属性
1 | @JsonIgnoreProperties(ignoreUnknown = true) |
配置用于序列化/反序列化pojo/json的objectmapper,如下所示:
1 2 3 4 5 | ObjectMapper mapper =new ObjectMapper(); // for Jackson version 1.X mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); // for Jackson version 2.X mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) |
这对我来说非常有效
1 2 3 | ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure( DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
这比所有方法都好。请参考此属性。
1 2 3 4 5 6 | import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); projectVO = objectMapper.readValue(yourjsonstring, Test.class); |
如果你用的是杰克逊2.0
1 2 | ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); |
根据文档,您可以忽略所选字段或所有Uknown字段:
1 2 3 4 5 6 | // to prevent specified fields from being serialized or deserialized // (i.e. not include in JSON output; or being set even if they were included) @JsonIgnoreProperties({"internalId","secretKey" }) // To ignore any unknown properties in JSON input without exception: @JsonIgnoreProperties(ignoreUnknown=true) |
它适用于我,代码如下:
1 2 | ObjectMapper mapper =new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
杰克逊抱怨说,因为它在类包装器中找不到名为"包装器"的字段。这样做是因为JSON对象有一个名为"wrapper"的属性。
我认为解决方法是将包装类的字段重命名为"wrapper",而不是"students"。
我已经尝试了下面的方法,它适用于与Jackson一起读取这种JSON格式。使用已经建议的解决方案:用
你的包装类
1 2 3 4 | public Class Wrapper{ private List<Student> students; //getters & setters here } |
包装类的建议
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public Class Wrapper{ private StudentHelper students; //getters & setters here // Annotate getter @JsonProperty("wrapper") StudentHelper getStudents() { return students; } } public class StudentHelper { @JsonProperty("Student") public List<Student> students; //CTOR, getters and setters //NOTE: If students is private annotate getter with the annotation @JsonProperty("Student") } |
但是,这将为您提供以下格式的输出:
1 | {"wrapper":{"student":[{"id":13,"name":Fred}]}} |
有关更多信息,请参阅https://github.com/fasterxml/jackson-annotations
希望这有帮助
此解决方案在读取JSON流时是通用的,只需要获取一些字段,而域类中未正确映射的字段可以忽略:
1 2 | import org.codehaus.jackson.annotate.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) |
一个详细的解决方案是使用一个工具,比如jsonschema2pojo,从json响应的模式中自动生成所需的域类,比如student。您可以通过任何在线JSON-to-Schema转换器实现后者。
因为JSON属性和Java属性的名称不匹配,所以注释以下字段的学生
1 2 3 4 5 | public Class Wrapper { @JsonProperty("wrapper") private List<Student> students; //getters & setters here } |
正如没人提到的,我以为我会…
问题是JSON中的属性称为"wrapper",wrapper.class中的属性称为"students"。
所以要么…
要么改变
1 2 3 4 | public Class Wrapper { private List<Student> students; //getters & setters here } |
到
1 2 3 4 | public Class Wrapper { private List<Student> wrapper; //getters & setters here } |
----或者----
将JSON字符串更改为
1 | {"students":[{"id":"13","name":"Fred"}]} |
你的输入
1 | {"wrapper":[{"id":"13","name":"Fred"}]} |
指示它是一个对象,具有名为"wrapper"的字段,该字段是学生的集合。所以我的建议是,
1 | Wrapper = mapper.readValue(jsonStr , Wrapper.class); |
其中
1 2 3 | class Wrapper { List<Student> wrapper; } |
我通过简单地更改pojo类的setter和getter方法的签名来解决这个问题。我所要做的就是更改getObject方法以匹配映射器正在查找的内容。在我的例子中,我最初有一个getImageURL,但是JSON数据有一个image_URL,它正在抛出映射器。我将setter和getter都改为getimage_url和setimage_url。
希望这有帮助。
对我有用的是把财产公之于众。它为我解决了这个问题。
就我而言,唯一的一行
也没用。
只要添加
1 | @JsonInclude(Include.NON_EMPTY) |
杰克逊2.4.0
这对我很管用
1 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
新的FireBase Android引入了一些巨大的变化;在文档副本下面:
[https://firebase.google.com/support/guides/firebase-android]:
更新Java模型对象
与2 .x SDK一样,FielBASE数据库会自动将您传递给EDCOX1×1的Java对象转换成JSON,并可以使用EDCOX1×2将JSON读入Java对象。
在新SDK中,当将JSON读入具有EDCOX1×2Ω的Java对象时,JSON中的未知属性现在默认被忽略,因此不再需要EDCOX1 OR 4 }。
为了在将Java对象写入JSON时排除字段/吸附器,注释现在被称为EDCOX1×5,而不是EDCOX1(6)。
1 2 3 4 5 6 7 8 9 10 11 |
1 2 3 4 5 6 7 8 9 10 |
如果JSON中没有Java类中的额外属性,则会在日志文件中看到此警告:
1 | W/ClassMapper: No setter/field for ignoreThisProperty found on class com.firebase.migrationguide.ChatMessage |
您可以通过在类上放置一个
将类字段设置为public而不是private。
1 2 3 4 5 |
POJO应定义为
响应类
1 2 3 4 | public class Response { private List<Wrapper> wrappers; // getter and setter } |
包装类
和映射器读取值
1 | Response response = mapper.readValue(jsonStr , Response.class); |
这可能是一个非常晚的响应,但只要将POJO更改为此值,就可以解决问题中提供的JSON字符串(因为输入字符串不在您的控制范围内,如您所说):
1 2 3 4 | public class Wrapper { private List<Student> wrapper; //getters & setters here } |
其他的可能性,这是一个在application.properties物业
谷歌把我带到这里,我惊讶地看到答案…所有的建议都是绕过错误(在开发过程中,它总是在后面咬4折),而不是解决错误,直到这位先生相信这样做而恢复过来!
1 | objectMapper.readValue(responseBody, TargetClass.class) |
用于将JSON字符串转换为类对象,缺少的是
通过Lombok,您的课程如下应该可以工作!!
1 2 3 4 5 |
在我的例子中,它很简单:REST服务JSON对象被更新(添加了一个属性),但是REST客户机JSON对象没有更新。一旦我更新了JSON客户机对象,"无法识别的字段…"异常就消失了。
JSON字符串未与映射类内联。更改输入字符串
1 |
或者更改映射类
1 2 3 4 | public class Wrapper { private List<Student> wrapper; //getters & setters here } |
您只需将列表字段从"students"更改为"wrapper",JSON文件就会被映射器查找。
在我的例子中,错误是由于以下原因造成的
最初它工作正常,然后我重命名了一个变量,使代码中的更改导致了这个错误。
然后我也申请了杰克逊的无知财产,但它不起作用。
最后,在重新定义getter和setters方法之后变量名已解决此错误
所以一定要重新定义getter和setter。
将包装类更改为
1 2 3 4 5 | public Class Wrapper { @JsonProperty("wrapper") // add this line private List<Student> students; } |
这样做的目的是将
另外,我个人更喜欢使用lombok注释作为getter和setter
1 2 3 4 5 6 7 | @Getter @Setter public Class Wrapper { @JsonProperty("wrapper") // add this line private List<Student> students; } |
由于我没有用lombok和
1 2 3 4 5 6 7 | public List<Student> getWrapper(){ return students; } public void setWrapper(List<Student> students){ this.students = students; } |
也可以使用Jackson来反序列化列表。
您需要验证正在解析的类的所有字段,使其与原始