带有JSON的杰克逊:无法识别的字段,未标记为可忽略


675

我需要将某个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
}

我不断收到此错误,“包装”返回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)

2
我发现这对避免创建包装器类很有用:Map dummy<String,Student> = myClientResponse.getEntity(new GenericType<Map<String, Student>>(){});然后Student myStudent = dummy.get("wrapper");
pulkitsinghal

6
JSON应该看起来像:String jsonStr =“ {\” students \“ \:[{\” id \“:\” 13 \“,\” name \“:\” Fred \“}]}”“; 如果你期待包装对象在你的休息POST请求
德米特里Algazin

2
相关(但不同)的问题:使用Jackson忽略JSON对象上的新字段
sleske 2015年

5
顺便说一句,这个问题的大多数答案实际上回答了一个不同的问题,即与我上面链接的问题类似的问题。
sleske,2015年

4
大多数答案有助于解决地毯问题,而不是实际解决问题 :(
NoobEditor

Answers:


990

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

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@JsonIgnoreProperties
class { ... }

它将忽略您尚未在POJO中定义的每个属性。当您只是在JSON中寻找几个属性而又不想编写整个映射时,此功能非常有用。有关更多信息,请访问Jackson的网站。如果要忽略任何未声明的属性,则应输入:

@JsonIgnoreProperties(ignoreUnknown = true)

9
Ariel,有什么方法可以在类外部声明吗?
乔恩·洛鲁索

4
我正在序列化我不拥有的类(无法修改)。在一个视图中,我想使用一组特定的字段进行序列化。在另一种观点中,我希望序列化不同的字段集(或者也许重命名JSON中的属性)。
乔恩·洛鲁索

11
我必须补充说,(ignoreUnknown = true)在注释您的课程时,您确实需要the ,否则它将无法正常工作
necromancer 2013年

85
朱利安,这不是对OP问题的正确答案。但是,我怀疑人们来这里是因为他们用谷歌搜索如何忽略未在POJO中定义的属性,这是第一个结果,因此他们最终投票赞成了Suresh的回应(这就是我的经历)。尽管原始问题与希望忽略未定义的属性无关。
Ric Jafe 2014年

5
这是一个非常愚蠢的默认设置,恕我直言,如果您向api添加属性,则整个序列化都会失败
headsvk

478

您可以使用

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

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


5
这对我没有用,但在未知属性上仍然
无法解决

1
您能否将至少一段代码粘贴到您正在执行的操作中,您可能在此错过了什么。通过执行此操作或使用“ @JsonIgnoreProperties(ignoreUnknown = true)”,应该可以解决您的问题。无论如何,祝你好运。
Suresh

27
FWIW-我不得不导入这个稍微不同的枚举:org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES
raf

9
^以上是
755

10
您还可以像以下这样链接这些调用:getObjectMapper()。disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
icfantv 2015年

126

第一个答案几乎是正确的,但是需要的是更改getter方法,NOT字段-字段是私有的(并且不会自动检测到);此外,如果两者均可见,则吸气剂优先于字段(也有一些方法可以使私有字段可见,但是如果要使用吸气剂则没有什么意义)

因此,getter应该命名为getWrapper(),或使用以下注释:

@JsonProperty("wrapper")

如果您更喜欢使用getter方法名称。


请详细说明-需要更改或注释哪个吸气剂?
弗朗斯

你的意思是用@JsonGetter(“ wrapper”)注释,对吗?
pedram bashiri,

@pedrambashiri不,我是说@JsonProperty。虽然@JsonGetter是合法的别名,但很少用作@JsonProperty获取,设置和字段的作品。setter和getter可以通过签名来区分(一个不带参数,返回非空值;另一个带一个参数)。
StaxMan

这是我一直在寻找的答案!听起来杰克逊在将源JSON映射到POJO时遇到麻烦,但是您可以通过标记getter来保证匹配。谢谢!
安德鲁·基尔纳

90

使用Jackson 2.6.0,这对我有用:

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

并设置:

@JsonIgnoreProperties(ignoreUnknown = true)

12
使用该配置注释是不必要的
neworld

您是否需要在课堂上同时配置ObjectMapper和Annotation?我想objectMapper可以修复所有问题,而无需注释每个类。我虽然使用注释。
祈祷之

您无需在同一课程中同时使用这两种设置。您也可以使用DI获取的全局单例实例ObjectMapper,以FAIL_ON_UNKNOWN_PROPERTIES全局设置属性。
user991710

您不需要两者,可以选择其中一个。
heez

58

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

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

    @JsonIgnoreProperties(ignoreUnknown = true)
  2. 配置ObjectMapper来对POJO / json进行序列化/反序列化,如下所示:

    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) 

2
为什么这应该是公认的答案?这只是告诉要忽略未知属性,而问题是找到一种方法来将json包装到对象中,此解决方案明确指出要忽略该对象。
Sayantan

42

这对我来说非常完美

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

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


2
投票不足,因为它无法回答OP的问题。忽略未知属性并不能解决他的问题,但是会给他留下一个Wrapper学生列表为null空的实例。
弗朗斯

37

这比全部效果更好,请参考此属性。

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

正常工作!
MADHAIYAN M 2015年

是的,这是解决我问题的人-与这篇文章的标题相匹配。
Scott Langeberg '16

答案对我来说很有效,这很容易。谢谢您
Touya Akira

29

如果您使用的是Jackson 2.0

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

为什么此配置对我无效?
zhaozhi '17

@zhaozhi取决于Jackson版本
Aalkhodiry

20

根据文档,您可以忽略所选字段或所有未知字段:

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

15

它通过以下代码为我工作:

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

15

添加setter和getters解决了这个问题,我认为实际的问题是如何解决而不是抑制/忽略错误。我收到错误“ 无法识别的字段..未标记为可忽略的..

尽管我在类顶部使用了以下注释,但它无法解析json对象并提供输入

@JsonIgnoreProperties(ignoreUnknown = true)

然后我意识到,在将“包装器”和“吸气剂”添加到“包装器”和“学生”中之后,我没有添加设置器和吸气器,它就像一个魅力。


这似乎是实际回答问题的唯一答案。所有其他答案都只是将未知属性标记为已忽略,但是“包装器”不是未知属性,这是我们试图解析的内容。
lbenedetto

14

杰克逊在抱怨,因为它在您的类包装器中找不到称为“包装器”的字段。这样做是因为您的JSON对象具有一个称为“包装器”的属性。

我认为解决方法是将Wrapper类的字段重命名为“ wrapper”而不是“ students”。


谢谢吉姆。我尝试了一下,但并没有解决问题。我想知道如果我错过了一些注解..
jshree

1
嗯,当您用Java创建等效数据然后使用Jackson将数据写成 JSON 时会发生什么。该JSON与上面的JSON之间的任何区别都应该是出了什么问题的线索。
Jim Ferrans 2010年

这个问题对我来说很有效,例如问题的例子。
sleske 2015年

14

我已经尝试过以下方法,并且可以与Jackson一起用于此类JSON格式读取。使用已经建议的解决方案:用以下方法注释getter@JsonProperty("wrapper")

您的包装课

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

希望这可以帮助


欢迎使用stackoverflow。提示,您可以使用{}工具栏中的符号来格式化代码段。
Leigh 2012年

11

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

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

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


10

如下注释现场学生,因为json属性和java属性的名称不匹配

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

9

正如没有人提到的那样,以为我会...

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

所以...

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

6

将您的班级字段设为公开而非私有

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

2
不良做法-这会破坏封装。
Downhillski

1
我听说过
Downhillski

用户使用类时,您的类会有风险,因为内部状态可以通过这些字段进行更改。
Downhillski


5

要么改变

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

5

您的输入

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

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

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

在哪里Wrapper定义为

class Wrapper {
    List<Student> wrapper;
}

5

新的Firebase Android进行了一些巨大的改变; 在文件副本下方:

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

更新您的Java模型对象

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

在新的SDK中,当使用读取JSON到Java对象中时DataSnapshot.getValue(),默认情况下会忽略JSON中的未知属性,因此您不再需要@JsonIgnoreExtraProperties(ignoreUnknown=true)

为了在将Java对象写入JSON时排除字段/获取器,现在调用注解@Exclude而不是@JsonIgnore

BEFORE

@JsonIgnoreExtraProperties(ignoreUnknown=true)
public class ChatMessage {
   public String name;
   public String message;
   @JsonIgnore
   public String ignoreThisField;
}

dataSnapshot.getValue(ChatMessage.class)

AFTER

public class ChatMessage {
   public String name;
   public String message;
   @Exclude
   public 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在类上添加注释。


4

就我而言,唯一的一行

@JsonIgnoreProperties(ignoreUnknown = true)

也没用

只需添加

@JsonInclude(Include.NON_EMPTY)

杰克逊2.4.0


4

这对我来说很完美

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

4

我通过简单地更改POJO类的setter和getter方法的签名来解决此问题。我要做的就是更改getObject方法以匹配映射器正在寻找的内容。在我的情况下,我最初有一个getImageUrl,但是JSON数据具有image_url,这使映射器无法使用。我将setter和getter都更改为getImage_url和setImage_url

希望这可以帮助。


您显然是对的:如果您想要的名称是xxx_yyy,则其调用方式为getXxx_yyy和setXxx_yyy。这是很奇怪的,但是可以。
sivi '16

3

POJO应该定义为

回应类

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

包装类

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

和映射器读取值

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

几乎。不是wrappers,但是wrapper
弗朗斯

@Frans Haha,谢谢您发现错误。我很自然地将复数用于集合。但是根据OP的问题,它应该是单数。
Dino Tw

3

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

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

3

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


3

这可能不是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.8
import com.fasterxml.jackson.annotation.JsonProperty; //com.fasterxml.jackson.core:jackson-databind:2.2.3

谢谢!import com.fasterxml.jackson.annotation.JsonProperty相反地为我工作:-)
phil

2

谷歌把我带到这里,我很惊讶地看到答案。所有的人都建议绕过错误(在开发中总是会咬人4倍),而不是解决这个错误,直到这位绅士对SO 有了信心!

objectMapper.readValue(responseBody, TargetClass.class)

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

通过龙目岛您的班级如下所示!

@Data
@Builder
public class TargetClass {
    private String a;
}

2

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

@JsonIgnoreProperties


也许一些进一步的解释或文档会很好
Benj

@JsonIgnoreProperties(ignoreUnknown = true)工作正常,谢谢
Guilherme
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.