杰克逊处理JSON数据:无法识别的字段,未标记为可忽略

993

我需要将特定的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
}

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

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

我一直收到这个错误,而“wrapper”返回null。我不确定缺少了什么。可以有人帮忙吗?

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)

3
我发现这个很有用,可以避免创建一个包装类:Map dummy<String,Student> = myClientResponse.getEntity(new GenericType<Map<String, Student>>(){}); 然后 Student myStudent = dummy.get("wrapper"); - pulkitsinghal
9
JSON应该长这样:String jsonStr = "{"students":[{"id":"13","name":"Fred"}]}"; 如果你期望在REST POST请求中接收封装对象。 - Dmitri Algazin
4
相关(但不同)问题:使用Jackson忽略JSON对象上的新字段 - sleske
6
顺便说一下,大多数回答这个问题的答案实际上回答了一个不同的问题,即类似于我链接的那个问题。 - sleske
8
大多数答案只是帮助掩盖问题,而不是真正解决它 :( - NoobEditor
显示剩余2条评论
51个回答

1372

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

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@JsonIgnoreProperties
class { ... }

如果您只想查找JSON中的几个属性而不想编写整个映射,则它将忽略您在POJO中未定义的每个属性。更多信息请参见Jackson's网站。如果您想忽略任何未声明的属性,应编写:

@JsonIgnoreProperties(ignoreUnknown = true)

15
Ariel,有没有办法将这个声明放在类外面? - Jon Lorusso
5
我正在对一些我不能修改的类进行序列化。在一个视图中,我想要对一组特定的字段进行序列化。在另一个视图中,我希望序列化不同的一组字段(或者可能重命名 JSON 中的属性)。 - Jon Lorusso
28
我必须补充一点,当给你的类添加注释时,你需要加上(ignoreUnknown = true),否则它将无法工作。 - necromancer
109
朱利安,这不是正确回答原帖问题的方法。但我猜人们来这里是因为他们通过谷歌搜索如何忽略在POJO中未定义的属性,这个页面是第一个结果,所以他们会点赞这篇回答和Suresh的回答(我就是这么做的)。虽然原问题与想要忽略未定义属性无关。 - Ric Jafe
19
我认为这是一个非常愚蠢的默认设置,如果您向您的API添加属性,则整个序列化过程将失败。 - headsvk
显示剩余13条评论

736
你可以使用
ObjectMapper objectMapper = getObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

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


7
这对我没用,它仍然在未知属性上失败了。 - Denys Kniazhev-Support Ukraine
36
FWIW -- 我不得不导入这个稍有不同的枚举:org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES。 - raf
13
以上内容适用于Jackson 2版本之前。 - 755
17
你还可以像这样链式调用:getObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)。 - icfantv
1
实际上,这是这个问题的最佳解决方案。 - Sai prateek
显示剩余4条评论

155

第一个答案几乎正确,但需要更改的是getter方法,而不是字段--字段是私有的(且不会自动检测);另外,如果字段和getter都可见,则getter优先于字段。(也有使私有字段可见的方法,但如果想要getter,那么没有太多意义)

因此,getter应该命名为getWrapper(),或者带有以下注解:

@JsonProperty("wrapper")

如果您喜欢保留 getter 方法的名称不变。


请详细说明 - 需要更改或注释哪个getter方法? - Frans
你的意思是用 @JsonGetter("wrapper") 注解,对吧? - pedram bashiri
@pedrambashiri 不,我指的是@JsonProperty。虽然@JsonGetter是一个合法的别名,但它很少被使用,因为@JsonProperty适用于getter、setter和字段;setter和getter可以通过签名进行区分(一个不带参数,返回非void;另一个带一个参数)。 - StaxMan
这就是我一直在寻找的答案!听起来Jackson在将源JSON映射到您的POJO时遇到了问题,但您可以通过标记getter方法来保证匹配。谢谢! - Andrew Kirna

141
使用Jackson 2.6.0,这对我起作用了。
private static final ObjectMapper objectMapper = 
    new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

或者使用以下设置:
@JsonIgnoreProperties(ignoreUnknown = true)

18
不需要那个配置注释。 - neworld
你需要在类上同时配置ObjectMapper和Annotation吗?我猜ObjectMapper会为所有类解决问题,而不需要对每个类进行注释。尽管如此,我还是使用了注释。 - prayagupa
你不需要在同一个类中同时使用这两个设置。你也可以使用DI来获取全局单例的 “ObjectMapper” 实例,以便在全局范围内设置“FAIL_ON_UNKNOWN_PROPERTIES”属性。 - filpa
1
你不需要两个,可以选择其中一个。 - heez

82

有两种方法可以实现:

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

    @JsonIgnoreProperties(ignoreUnknown = true)
    
  2. 配置ObjectMapper,将POJO/JSON序列化/反序列化为以下内容:

  3. 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) 
    

3
为什么这个答案应该被接受?它只是告诉我们忽略未知的属性,而问题是要找到一种方法将JSON包装成一个对象,而这个解决方案明显告诉我们要忽略这一点。 - Sayantan
仅使用第一个选项给出了很好的答案。 - Juan Enrique Riquelme

70

添加getter和setter解决了问题,我感觉实际问题是如何解决而不是如何抑制/忽略错误。

我收到的错误信息是"Unrecognized field.. not marked as ignorable.."

尽管我在类的顶部使用了下面的注释,但它无法解析JSON对象并为我提供输入:

@JsonIgnoreProperties(ignoreUnknown = true)

然后我意识到我没有添加getter和setter,在"Wrapper"和"Student"中添加getter和setter之后,问题得到了很好地解决。


2
这似乎是唯一一个真正回答了问题的答案。所有其他答案都只是将未知属性标记为被忽略,但“wrapper”不是未知属性,它是我们正在尝试解析的内容。 - lbenedetto

47

这对我来说完美地起作用了

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

@JsonIgnoreProperties(ignoreUnknown = true)注解没有生效。


3
因为回答没有解决问题,所以被投票下降。忽略未知属性不能解决他的问题,但会使他得到一个Wrapper实例,其中学生列表为null或空。 - Frans

44

这个属性比“所有”更好,请参考此属性。

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

是的,这就是解决了我的问题 - 与这篇帖子的标题相匹配。 - Scott Langeberg
答案对我很有帮助,而且非常容易。谢谢。 - Touya Akira
1
之后我的projectVO数据为空。你的json字符串有值,但是projectVO字段为空。有人能帮忙吗? - sashikanta
这真的很有效,而且POJO也不需要任何修改! - Anvita Shukla

35

如果您正在使用Jackson 2.0

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

为什么这个配置对我没有任何影响? - zhaozhi
@zhaozhi 这取决于Jackson的版本。 - Aalkhodiry

26
根据文档,您可以忽略选定字段或所有未知字段。
 // 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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接