杰克逊与JSON:未被识别的领域,没有标记为可忽略

时间:2010-12-20 04:02:51

标签: java json data-binding jackson

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

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

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)

44 个答案:

答案 0 :(得分:838)

您可以使用杰克逊的班级注释:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@JsonIgnoreProperties
class { ... }

它会忽略您在POJO中未定义的每个属性。当你只是在JSON中寻找几个属性并且不想编写整个映射时非常有用。有关详情,请访问Jackson's website。如果要忽略任何未声明的属性,则应写入:

@JsonIgnoreProperties(ignoreUnknown = true)

答案 1 :(得分:397)

您可以使用

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

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

答案 2 :(得分:117)

第一个答案几乎是正确的,但是需要的是改变getter方法,NOT字段 - 字段是私有的(而不是自动检测的);此外,如果两者都可见,则getters优先于字段。(有一些方法可以使私有字段可见,但是如果你想获得getter则没有多大意义)

因此,getter应该命名为getWrapper(),或者注释为:

@JsonProperty("wrapper")

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

答案 3 :(得分:75)

使用Jackson 2.6.0,这对我有用:

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

并设置:

@JsonIgnoreProperties(ignoreUnknown = true)

答案 4 :(得分:45)

可以通过两种方式实现:

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

    @JsonIgnoreProperties(ignoreUnknown = true)
    
  2. 配置用于序列化/反序列化POJO / json的ObjectMapper,如下所示:

    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) 
    

答案 5 :(得分:39)

这对我来说非常有用

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

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

答案 6 :(得分:35)

这比All更好用,请参考这个属性。

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

答案 7 :(得分:26)

如果您使用的是Jackson 2.0

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

答案 8 :(得分:17)

根据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)

答案 9 :(得分:14)

使用以下代码对我有用:

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

答案 10 :(得分:12)

杰克逊正在抱怨,因为它无法在你的班级Wrapper中找到一个名为“包装器”的字段。这样做是因为你的JSON对象有一个叫做“wrapper”的属性。

我认为修复方法是将您的Wrapper类的字段重命名为“wrapper”而不是“student”。

答案 11 :(得分:10)

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

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

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

答案 12 :(得分:10)

我已经尝试了以下方法,它适用于与杰克逊这样的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

希望这有帮助

答案 13 :(得分:9)

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

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

答案 14 :(得分:8)

正如没有其他人提到的那样,我想...... [/ p>

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

所以要么......

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

答案 15 :(得分: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"}]}

答案 16 :(得分:5)

您的输入

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

表示它是一个Object,其中包含一个名为“wrapper”的字段,它是一个学生集合。所以我的推荐是,

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

其中Wrapper定义为

class Wrapper {
    List<Student> wrapper;
}

答案 17 :(得分:5)

如果由于某种原因您无法将 @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;

@Provider
public class CustomObjectMapperProvider implements ContextResolver<ObjectMapper> {

    private ObjectMapper objectMapper;

    @Override
    public 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;
    }
}

答案 18 :(得分:4)

就我而言,唯一的一行

@JsonIgnoreProperties(ignoreUnknown = true)

也没有工作。

添加

@JsonInclude(Include.NON_EMPTY)

Jackson 2.4.0

答案 19 :(得分:4)

这对我来说很完美

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

答案 20 :(得分:4)

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

希望这有帮助。

答案 21 :(得分:4)

对我有用的是公开财产。它解决了我的问题。

答案 22 :(得分:3)

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

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

更新Java模型对象

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

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

要在将Java对象写入JSON时排除字段/ getter,现在将注释称为@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注释。

答案 23 :(得分:3)

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

答案 24 :(得分:3)

公开设置为您的课程字段私有

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

答案 25 :(得分:3)

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

答案 26 :(得分:2)

这个问题已经有很多答案了。我正在添加现有答案。

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

在您的应用程序配置文件中定义一个 bean 来创建这样的 jackson 对象映射器。

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

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

谢谢。

答案 27 :(得分:2)

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

if

答案 28 :(得分:1)

就我而言,它很简单:REST服务JSON对象已更新(已添加属性),但REST客户端JSON对象未更新。一旦我更新了JSON客户端对象,“无法识别的字段......”异常就消失了。

答案 29 :(得分:1)

谷歌把我带到了这里,我很惊讶地看到了答案...所有人都建议绕过错误(总是在开发后的4倍之后咬回来)而不是解决它,直到this gentleman因信仰而恢复!

objectMapper.readValue(responseBody, TargetClass.class)

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

通过lombok您的课程如下所示!

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

答案 30 :(得分:1)

不知何故,经过45个帖子和10年的努力,没有人为我的案件发布正确的答案。

@Data //Lombok
public class MyClass {
    private int foo;
    private int bar;

    @JsonIgnore
    public int getFoobar() {
      return foo + bar;
    }
}

在我的情况下,我们有一个名为getFoobar()的方法,但是没有foobar属性(因为它是从其他属性计算出来的)。 @JsonIgnoreProperties在课堂上无效。

解决方案是使用@JsonIgnore

注释方法

答案 31 :(得分:1)

这可能不是OP所遇到的问题,但是如果有人以我犯的相同错误来到这里,那么这将帮助他们解决问题。当我使用来自JsonProperty批注的不同依赖项的ObjectMapper时,遇到了与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

答案 32 :(得分:0)

没有设置器/获取器的最短解决方案是将@JsonProperty添加到类字段中:

public class Wrapper {
    @JsonProperty
    private List<Student> wrapper;
}

public class Student {
    @JsonProperty
    private String name;
    @JsonProperty
    private String id;
}

此外,您还称学生在json中列出了“包装器”,因此杰克逊希望有一个带有“包装器”字段的班级。

答案 33 :(得分:0)

以防万一其他人像我一样使用 force-rest-api,以下是我如何使用此讨论来解决它 (Kotlin):

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 的旧版本。

答案 34 :(得分:0)

添加setter和getter可以解决问题,我认为真正的问题是如何解决而不是抑制/忽略错误。 我收到错误消息“ 无法识别的字段..未标记为可忽略。.

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

  

@JsonIgnoreProperties(ignoreUnknown = true)

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

答案 35 :(得分:0)

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)

答案 36 :(得分:0)

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

private boolean isActive;

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

public isActive(){
   return isActive;
}

就我而言,我只是更改了吸气剂和吸气剂。

private boolean isActive;

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

public getIsActive(){
   return isActive;
}

它能够识别该字段。

答案 37 :(得分:0)

在我的情况下,我必须添加公共获取器和设置器以将字段保留为私有。

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

我使用jackson-databind 2.10.0.pr3。

答案 38 :(得分:0)

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

@JsonIgnoreProperties

答案 39 :(得分:0)

将Wrapper类更改为

public Class Wrapper {

          @JsonProperty("wrapper")  // add this line
          private List<Student> students;
}

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

另外,我个人更喜欢将Lombok Annotations用于Getters and Setters

@Getter
@Setter
public Class Wrapper {

          @JsonProperty("wrapper")  // add this line
          private List<Student> students;
}

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

public List<Student> getWrapper(){
     return students;
}

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

同时检查this以使用Jackson对列表进行反序列化。

答案 40 :(得分:0)

在我的情况下,错误来自于以下原因

  • 最初它工作正常,然后我重命名了一个变量,制作了 代码中的更改,它给了我这个错误。

  • 然后我也申请了杰克逊无知的财产但是没有用。

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

因此,请确保重新定义吸气剂和制定者。

答案 41 :(得分:0)

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

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

或更改您的映射类

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

答案 42 :(得分:0)

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

答案 43 :(得分:-1)

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

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