Jackson with JSON:无法识别的字段,未标记为可忽略

我需要将某个JSON字符串转换为Java对象。我正在使用Jackson进行JSON处理。我无法控制输入JSON(我从Web服务读取)。这是我的输入JSON:

{"wrapper":[{"id":"13","name":"Fred"}]}

这是一个简化的用例:

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);}

我的实体类是:

public Class Student {private String name;private String id;//getters & setters for name & id here}

我的Wrapper类基本上是一个容器对象,用于获取我的学生列表:

public Class Wrapper {private List<Student> students;//getters & setters here}

我一直收到这个错误,“包装器”返回null。我不确定缺少什么。有人能帮忙吗?

org.codehaus.jackson.map.exc.UnrecognizedPropertyException:Unrecognized field "wrapper" (Class Wrapper), not marked as ignorableat [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)
1159902 次浏览

Jackson抱怨是因为它在您的类Wrapper中找不到一个名为“包装器”的字段。它这样做是因为您的JSON对象有一个名为“包装器”的属性。

我认为解决方法是将Wrapper类的字段重命名为“包装器”而不是“学生”。

第一个答案几乎是正确的,但是需要改变getter方法,而不是field-field是私有的(并且不是自动检测的);此外,如果两个字段都可见,getter优先于字段。(也有让私有字段可见的方法,但如果你想拥有getter,那就没什么意义了)

所以getter应该被命名为getWrapper(),或者注释为:

@JsonProperty("wrapper")

如果您喜欢按原样使用getter方法名称。

您可以使用Jackson的类级注释:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties
@JsonIgnorePropertiesclass { ... }

它将忽略您在POJO中未定义的每个属性。当你只是在JSON中查找几个属性并且不想编写整个映射时非常有用。更多信息在杰克逊的网站。如果你想忽略任何未声明的属性,你应该写:

@JsonIgnoreProperties(ignoreUnknown = true)

问题是您在JSON中的属性称为“包装器”,而您在Wrapper.class中的属性称为“学生”。

所以要么…

  1. 更正类或JSON中属性的名称。
  2. 根据StaxMan的注释注释您的属性变量。
  3. 注释setter(如果您有)

我试过下面的方法,它适用于杰克逊的JSON格式读取。使用已经建议的解决方案:用@JsonProperty("wrapper")

注释getter

你的包装类

public Class Wrapper{private List<Student> students;//getters & setters here}

我对包装类的建议

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")}

但是,这将为您提供格式的输出:

{"wrapper":{"student":[{"id":13,"name":Fred}]}}

有关更多信息,请参阅https://github.com/FasterXML/jackson-annotations

您可以使用

ObjectMapper objectMapper = getObjectMapper();objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

它将忽略所有未声明的属性。

此解决方案在读取json流时是通用的,只需要获取一些字段,而在域类中未正确映射的字段可以忽略:

import org.codehaus.jackson.annotate.JsonIgnoreProperties;@JsonIgnoreProperties(ignoreUnknown = true)

一个详细的解决方案是使用jsonSchema2pojo等工具从json响应的模式中自动生成所需的域类,例如学生。您可以通过任何在线json到模式转换器执行后者。

这对我来说很管用

ObjectMapper objectMapper = new ObjectMapper();objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

@JsonIgnoreProperties(ignoreUnknown = true)注释没有。

这比所有作品更好,请参考此属性。

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);

如果您使用的是Jackson 2.0

ObjectMapper mapper = new ObjectMapper();mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

POJO应该定义为

响应类

public class Response {private List<Wrapper> wrappers;// getter and setter}

包装类

public class Wrapper {private String id;private String name;// getters and setters}

和mapper读取值

Response response = mapper.readValue(jsonStr , Response.class);

对我有用的是将财产公之于众。

要么改变

public Class Wrapper {private List<Student> students;//getters & setters here}

public Class Wrapper {private List<Student> wrapper;//getters & setters here}

----或----

将JSON字符串更改为

{"students":[{"id":"13","name":"Fred"}]}

对我来说,唯一的一条线

@JsonIgnoreProperties(ignoreUnknown = true)

也没起作用。

只需添加

@JsonInclude(Include.NON_EMPTY)

杰克逊2.4.0

这对我来说很完美

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

我通过简单地更改POJO类的setter和getter方法的签名来解决这个问题。我所要做的就是更改getObject方法以匹配映射器要查找的内容。在我的情况下,我最初有一个获取图片url,但JSON数据有image_url,这使映射器失效。我将我的setter和getter都更改为getImage_url和setImage_url

使用Jackson 2.6.0,这对我很有效:

private static final ObjectMapper objectMapper =new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

和设置:

@JsonIgnoreProperties(ignoreUnknown = true)

它使用以下代码为我工作:

ObjectMapper mapper =new ObjectMapper();mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

您只需将List字段从“学生”更改为“包装器”,只需json文件,映射器就会查找它。

根据doc,您可以忽略选定的字段或所有未知字段:

 // 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)

您的输入

{"wrapper":[{"id":"13","name":"Fred"}]}

表示它是一个对象,有一个名为“包装器”的字段,这是一个学生集合。所以我的建议是,

Wrapper = mapper.readValue(jsonStr , Wrapper.class);

其中Wrapper定义为

class Wrapper {List<Student> wrapper;}

在我的情况下,它很简单:更新了REST-service JSON对象(添加了一个属性),但REST-clientJSON对象没有。一旦我更新了JSON客户端对象,“无法识别的字段…”异常就消失了。

您的json字符串与映射的类不内联。更改输入字符串

String jsonStr = "{\"students\"\:[{\"id\":\"13\",\"name\":\"Fred\"}]}";

或更改映射类

public class Wrapper {private List<Student> wrapper;//getters & setters here}

新的Firebase Android引入了一些巨大的变化;下面的文档副本:

[https://firebase.google.com/support/guides/firebase-android]:]

更新Java模型对象

与2. x SDK一样,Firebase数据库会自动将传递给DatabaseReference.setValue()的Java对象转换为JSON,并且可以使用DataSnapshot.getValue()将JSON读取到Java对象中。

在新的SDK中,当将JSON读入具有DataSnapshot.getValue()的Java对象时,JSON中的未知属性现在默认被忽略,因此您不再需要@JsonIgnoreExtraProperties(ignoreUnknown=true)

为了在将Java对象写入JSON时排除字段/getter,注释现在称为@Exclude而不是@JsonIgnore

BEFORE
@JsonIgnoreExtraProperties(ignoreUnknown=true)public class ChatMessage {public String name;public String message;@JsonIgnorepublic String ignoreThisField;}
dataSnapshot.getValue(ChatMessage.class)

AFTER
public class ChatMessage {public String name;public String message;@Excludepublic String ignoreThisField;}
dataSnapshot.getValue(ChatMessage.class)

如果您的JSON中有一个不在Java类中的额外属性,您将在日志文件中看到此警告:

W/ClassMapper: No setter/field for ignoreThisProperty found on class com.firebase.migrationguide.ChatMessage

您可以通过在类上添加@IgnoreExtraProperties注释来消除此警告。如果您希望Firebase数据库的行为与2. x SDK中的行为相同,并在存在未知属性时抛出异常,您可以在类上添加@ThrowOnExtraProperties注释。

由于json属性和java属性的名称不匹配,请将字段同学标注如下

public Class Wrapper {@JsonProperty("wrapper")private List<Student> students;//getters & setters here}

它可以通过两种方式实现:

  1. 标记POJO以忽略未知属性

    @JsonIgnoreProperties(ignoreUnknown = true)
  2. Configure ObjectMapper that serializes/De-serializes the POJO/json as below:

    ObjectMapper mapper =new ObjectMapper();// for Jackson version 1.Xmapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);// for Jackson version 2.Xmapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

您需要验证您正在解析的类的所有字段,使其与原始JSONObject相同。它对我和我的情况都有帮助。

@JsonIgnoreProperties(ignoreUnknown = true)根本没有帮助。

这可能是一个很晚的响应,但只需将POJO更改为this就可以解决问题中提供的json字符串(因为,输入字符串不在您所说的控制中):

public class Wrapper {private List<Student> wrapper;//getters & setters here}

谷歌把我带到这里,我很惊讶地看到答案……所有人都建议绕过错误(它总是在开发后期咬回4折),而不是解决它,直到这位先生通过对SO的信心恢复!

objectMapper.readValue(responseBody, TargetClass.class)

用于将json String转换为类对象,缺少的是TargetClass应该有公共getter/setters。OP的问题片段也缺少相同的内容!:)

通过龙目岛你的类如下应该工作!

@Data@Builderpublic class TargetClass {private String a;}

在我的情况下错误是由于以下原因

  • 最初它工作得很好,然后我重命名了一个变量,制作了代码发生了变化,它给了我这个错误。

  • 然后我也应用了杰克逊无知属性,但它不起作用。

  • 最后在重新定义我的getter和setter方法之后我的变量名称此错误已解决

所以一定要重新调整getter和setter。

将Wrapper类更改为

public Class Wrapper {
@JsonProperty("wrapper")  // add this lineprivate List<Student> students;}

这样做的目的是将students字段识别为json对象的wrapper键。

此外,我个人更喜欢使用龙目岛注解作为Getters和Setters

@Getter@Setterpublic Class Wrapper {
@JsonProperty("wrapper")  // add this lineprivate List<Student> students;}

由于我还没有用Lombok和@JsonProperty一起测试上述代码,我建议您将以下代码添加到Wrapper类中,以覆盖Lombok的默认getter和setter。

public List<Student> getWrapper(){return students;}
public void setWrapper(List<Student> students){this.students = students;}

还要选中这个以使用Jackson对列表进行反序列化。

设置公共你的类字段不是私人

public Class Student {public String name;public String id;//getters & setters for name & id here}

另一种可能性是application.propertiesspring.jackson.deserialization.fail-on-unknown-properties=false,这不需要在您的应用程序中更改任何其他代码。当您认为合约稳定时,您可以删除此属性或将其标记为true。

这可能与OP遇到的问题不同,但如果有人在这里犯了与我相同的错误,那么这将帮助他们解决问题。当我使用来自不同依赖项的ObjectMapper作为JsonProperty注释时,我遇到了与OP相同的错误。

这工作:

import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.annotation.JsonProperty;

不工作:

import org.codehaus.jackson.map.ObjectMapper; //org.codehaus.jackson:jackson-mapper-asl:1.8.8import com.fasterxml.jackson.annotation.JsonProperty; //com.fasterxml.jackson.core:jackson-databind:2.2.3

导入com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@Json忽略属性

在我的例子中,我必须添加公共getter和setter以保持字段私有。

ObjectMapper mapper = new ObjectMapper();Application application = mapper.readValue(input, Application.class);

我使用杰克逊数据库2.10.0.pr3。

当我们生成getter和setter时,特别是以'is'关键字开头的,IDE通常会删除'is'。

private boolean isActive;
public void setActive(boolean active) {isActive = active;}
public isActive(){return isActive;}

在我的例子中,我只是更改了getter和setter。

private boolean isActive;
public void setIsActive(boolean active) {isActive = active;}
public getIsActive(){return isActive;}

它能够识别这个领域。

FAIL_ON_UNKNOWN_PROPERTIES选项默认为true:

FAIL_ON_UNKNOWN_PROPERTIES (default: true)Used to control whether encountering of unknown properties (one for which there is no setter; and there is no fallback "any setter" method defined using @JsonAnySetter annotation) should result in a JsonMappingException (when enabled), or just quietly ignored (when disabled)

添加setter和getter解决了问题,我觉得实际问题是如何解决它,而不是如何抑制/忽略错误。错误信息:“无法识别的字段…未标记为可忽略…

虽然我在类的顶部使用了下面的注释,但它无法解析json对象并给我输入

@JsonIgnoreProperties()

然后我意识到我没有添加setter和getter,在将setter和getter添加到“包装器”和“学生”之后,它就像一个魅力。

没有setter/getter的最短解决方案是将@JsonProperty添加到类字段:

public class Wrapper {@JsonPropertyprivate List<Student> wrapper;}
public class Student {@JsonPropertyprivate String name;@JsonPropertyprivate String id;}

此外,您在json中将学生列表称为“包装器”,因此Jackson希望类具有名为“包装器”的字段。

不知何故,在45个帖子和10年后,没有人发布我案件的正确答案。

@Data //Lombokpublic class MyClass {private int foo;private int bar;
@JsonIgnorepublic int getFoobar() {return foo + bar;}}

在我的例子中,我们有一个名为getFoobar()的方法,但没有foobar属性(因为它是从其他属性计算出来的)。

解决方案是用@JsonIgnore注释方法

如果由于某种原因您无法将@JsonIgnoreProperties注释添加到您的类中,并且您在Web服务器/容器(例如Jetty)中。您可以在自定义提供程序中创建和自定义ObjectMapper

import javax.ws.rs.ext.ContextResolver;import javax.ws.rs.ext.Provider;
import com.fasterxml.jackson.annotation.JsonInclude.Include;import com.fasterxml.jackson.databind.DeserializationFeature;import com.fasterxml.jackson.databind.ObjectMapper;
@Providerpublic class CustomObjectMapperProvider implements ContextResolver<ObjectMapper> {
private ObjectMapper objectMapper;
@Overridepublic ObjectMapper getContext(final Class<?> cls) {return getObjectMapper();}
private synchronized ObjectMapper getObjectMapper() {if(objectMapper == null) {objectMapper = new ObjectMapper();objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);}return objectMapper;}}

如果您想将@JsonIgnoreProperties应用于应用程序中的所有类,那么最好的方法是覆盖Spring引导默认杰克逊对象。

在您的应用程序配置文件中定义一个bean来创建杰克逊对象映射器,如下所示。

@Beanpublic ObjectMapper getObjectMapper() {ObjectMapper mapper = new ObjectMapper();mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);return mapper;}

现在,您不需要标记每个类,它将忽略所有未知属性。

以防其他人像我一样使用强制休息API,以下是我如何使用这个讨论来解决它(静态编程语言):

var result = forceApi.getSObject("Account", "idhere")result.jsonMapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,  false)val account: Account = result.`as`(Account::class.java)

看起来force-rest api使用的是旧版本的jackson's。

按照这个留档,您可以使用Jackson2ObjectMapperBuilder来构建您的ObjectMapper:

@AutowiredJackson2ObjectMapperBuilder objectBuilder;
ObjectMapper mapper = objectBuilder.build();String json = "{\"id\": 1001}";

默认情况下,Jackson2ObjectMapperBuilder会禁用错误未识别的属性异常。

Json字段:

 "blog_host_url": "some.site.com"

静态编程语言领域

var blogHostUrl: String = "https://google.com"

在我的情况下,我只需要在我的dataClass中使用@JsonProperty注释。

示例:

data class DataBlogModel(@JsonProperty("blog_host_url") var blogHostUrl: String = "https://google.com")

文章来源:https://www.baeldung.com/jackson-name-of-property

ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true);

当我的JSON有效负载包含API无法识别的属性时,我遇到过一次。解决方案是重命名/删除违规属性。

我遇到了类似的问题,唯一的区别是我使用的是YAML文件而不是JSON文件。所以我在创建ObjectMapper时使用了YamlFactory()。此外,我JavaPOJO的属性是私有的。然而,所有这些答案中提到的解决方案都没有帮助。我的意思是,它停止抛出错误并开始返回Java对象,但java对象的属性将为null。

我只是做了以下事情:

objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

而不需要:-

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

现在,我能够将Yaml文件中的数据反序列化为Java对象。现在所有属性都不为空。此解决方案也适用于JSON方法。

下面是我试图压制不想解析的未知道具。共享静态编程语言代码

val myResponse = jacksonObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).readValue(serverResponse, FooResponse::class.java)

Java11及更高版本的简单解决方案:

var mapper = new ObjectMapper().registerModule(new JavaTimeModule()).disable(FAIL_ON_UNKNOWN_PROPERTIES).disable(WRITE_DATES_AS_TIMESTAMPS).enable(ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);

重要的是要忽略禁用“FAIL_ON_UNKNOWN_PROPERTIES”