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

jsh*_*ree 602 java data-binding json jackson

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

{"wrapper":[{"id":"13","name":"Fred"}]}
Run Code Online (Sandbox Code Playgroud)

这是一个简化的用例:

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);
}
Run Code Online (Sandbox Code Playgroud)

我的实体类是:

public Class Student { 
    private String name;
    private String id;
    //getters & setters for name & id here
}
Run Code Online (Sandbox Code Playgroud)

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

public Class Wrapper {
    private List<Student> students;
    //getters & setters here
}
Run Code Online (Sandbox Code Playgroud)

我一直收到这个错误,"包装"返回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)
Run Code Online (Sandbox Code Playgroud)

Ari*_*gan 928

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

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@JsonIgnoreProperties
class { ... }
Run Code Online (Sandbox Code Playgroud)

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

@JsonIgnoreProperties(ignoreUnknown = true)
Run Code Online (Sandbox Code Playgroud)

  • Julián,这不是OP问题的正确答案.然而,我怀疑人们来到这里是因为他们谷歌如何忽略未在POJO中定义的属性,这是第一个结果,所以他们最终投票和Suresh的回应(这就是发生在我身上的事情).虽然原始问题与想要忽略未定义属性无关. (79认同)
  • 我必须补充一点,在注释你的类时你确实需要`(ignoreUnknown = true)`否则它将无法工作 (10认同)
  • 阿里尔,有没有办法在课堂上宣布这个? (9认同)
  • 我正在序列化我不拥有的类(无法修改).在一个视图中,我想用一组字段序列化.在另一个视图中,我想要一组不同的字段序列化(或者可能重命名JSON中的属性). (4认同)
  • 我还没有这样做,但我相信你可以在注释处理代码中找到某个地方并以编程方式添加行为,尽管我无法想到你为什么要这样做.能给我举个例子? (3认同)
  • 这是一个非常愚蠢的默认设置,恕我直言,如果您向api添加属性,则整个序列化都会失败 (2认同)
  • @ycomp,这些不是 2 种语法,`@JsonIgnoreProperties` 是注释,`@JsonIgnoreProperties(ignoreUnknown = true)` 是一种可能的使用方式。您还可以按照 Jackson 的文档中的说明指定要忽略的字段(例如`@JsonIgnoreProperties({ "extra", "uselessValue" })`) (2认同)

Sur*_*ani 432

您可以使用

ObjectMapper objectMapper = getObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Run Code Online (Sandbox Code Playgroud)

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

  • FWIW - 我必须导入这个略有不同的枚举:org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES (24认同)
  • ^以上是2之前的杰克逊版本 (9认同)
  • 你也可以链接这些调用,如:getObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) (9认同)
  • 这对我来说不起作用,它仍然在未知属性上失败 (5认同)

Sta*_*Man 123

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

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

@JsonProperty("wrapper")
Run Code Online (Sandbox Code Playgroud)

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


Sco*_*ott 80

使用Jackson 2.6.0,这对我有用:

private static final ObjectMapper objectMapper = 
    new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Run Code Online (Sandbox Code Playgroud)

并设置:

@JsonIgnoreProperties(ignoreUnknown = true)
Run Code Online (Sandbox Code Playgroud)

  • 使用该配置注释是不必要的 (10认同)

Ana*_*ika 50

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

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

    @JsonIgnoreProperties(ignoreUnknown = true)
    
    Run Code Online (Sandbox Code Playgroud)
  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) 
    
    Run Code Online (Sandbox Code Playgroud)

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

ddc*_*ddc 45

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

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

@JsonIgnoreProperties(ignoreUnknown = true)

然后我意识到我没有添加 setter 和 getter,在将 setter 和 getter 添加到“Wrapper”和“Student”之后,它就像一个魅力。

  • 这似乎是真正回答问题的唯一答案。所有其他答案只是将未知属性标记为忽略,但“包装器”不是未知属性,而是我们要解析的属性。 (3认同)

小智 41

这对我来说非常合适

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(
    DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Run Code Online (Sandbox Code Playgroud)

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

  • 你输入了正确的JsonIgnoreProperties? (2认同)
  • 因为它没有回答OP的问题而被低估了.忽略未知属性并不能解决他的问题,但是他留下了一个`Wrapper`实例,其中学生列表为"null"或为空. (2认同)

小智 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);
Run Code Online (Sandbox Code Playgroud)


Aal*_*iry 27

如果您使用的是Jackson 2.0

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
Run Code Online (Sandbox Code Playgroud)


tom*_*ozb 18

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

 // 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)
Run Code Online (Sandbox Code Playgroud)


Jim*_*ans 14

杰克逊抱怨是因为它无法在你的班级Wrapper中找到一个被称为"包装器"的字段.这样做是因为你的JSON对象有一个叫做"wrapper"的属性.

我认为修复是将您的Wrapper类的字段重命名为"wrapper"而不是"students".


小智 14

我尝试了下面的方法,它适用于与杰克逊这样的JSON格式阅读.使用已经建议的解决方案:使用注释getter@JsonProperty("wrapper")

你的包装类

public Class Wrapper{ 
  private List<Student> students;
  //getters & setters here 
} 
Run Code Online (Sandbox Code Playgroud)

我对包装类的建议

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")
}
Run Code Online (Sandbox Code Playgroud)

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

{"wrapper":{"student":[{"id":13,"name":Fred}]}}
Run Code Online (Sandbox Code Playgroud)

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

希望这可以帮助


小智 14

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

ObjectMapper mapper =new ObjectMapper();    
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Run Code Online (Sandbox Code Playgroud)


Ale*_*mov 12

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

var mapper = new ObjectMapper()
        .registerModule(new JavaTimeModule())
        .disable(FAIL_ON_UNKNOWN_PROPERTIES)
        .disable(WRITE_DATES_AS_TIMESTAMPS)
        .enable(ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
Run Code Online (Sandbox Code Playgroud)

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


Geo*_*rou 10

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

import org.codehaus.jackson.annotate.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
Run Code Online (Sandbox Code Playgroud)

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


小智 10

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

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


Ted*_*pin 9

没有人提到过,以为我会......

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

所以要么......

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


Blu*_*eft 9

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

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

    @JsonIgnore
    public int getFoobar() {
      return foo + bar;
    }
}
Run Code Online (Sandbox Code Playgroud)

就我而言,我们有一个名为 的方法getFoobar(),但没有foobar属性(因为它是根据其他属性计算的)。 @JsonIgnoreProperties在课堂上不起作用。

解决方案是将该方法注释为@JsonIgnore

  • 投票因为这也帮助了我。在研究了“@JsonIgnoreProperties”并添加虚拟成员之后,我发现了这个,它完全满足了我的需要。谢谢。 (3认同)

sup*_*rdo 7

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


cwa*_*cwa 7

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

这有效:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonProperty;
Run Code Online (Sandbox Code Playgroud)

不起作用:

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
Run Code Online (Sandbox Code Playgroud)


Roh*_*esh 6

对我有用的是将财产公之于众。它为我解决了这个问题。


sag*_*gar 5

改变

public Class Wrapper {
    private List<Student> students;
    //getters & setters here
}
Run Code Online (Sandbox Code Playgroud)

public Class Wrapper {
    private List<Student> wrapper;
    //getters & setters here
}
Run Code Online (Sandbox Code Playgroud)

- - 要么 - -

将您的JSON字符串更改为

{"students":[{"id":"13","name":"Fred"}]}
Run Code Online (Sandbox Code Playgroud)


小智 5

就我而言,唯一的线路

@JsonIgnoreProperties(ignoreUnknown = true)

也没有用。

只需添加

@JsonInclude(Include.NON_EMPTY)
Run Code Online (Sandbox Code Playgroud)

杰克逊 2.4.0


Nia*_*ath 5

这对我来说非常有效

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Run Code Online (Sandbox Code Playgroud)


小智 5

你的意见

{"wrapper":[{"id":"13","name":"Fred"}]}
Run Code Online (Sandbox Code Playgroud)

表示它是一个Object,带有一个名为"wrapper"的字段,它是一个学生集合.所以我的推荐是,

Wrapper = mapper.readValue(jsonStr , Wrapper.class);
Run Code Online (Sandbox Code Playgroud)

在哪里Wrapper定义为

class Wrapper {
    List<Student> wrapper;
}
Run Code Online (Sandbox Code Playgroud)


Thi*_*ryC 5

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

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

更新您的 Java 模型对象

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

在新的 SDK 中,当使用 将 JSON 读入 Java 对象时DataSnapshot.getValue(),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)
Run Code Online (Sandbox Code Playgroud)
AFTER

public class ChatMessage {
   public String name;
   public String message;
   @Exclude
   public String ignoreThisField;
}

dataSnapshot.getValue(ChatMessage.class)
Run Code Online (Sandbox Code Playgroud)

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

W/ClassMapper: No setter/field for ignoreThisProperty found on class com.firebase.migrationguide.ChatMessage
Run Code Online (Sandbox Code Playgroud)

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


nev*_*ter 5

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

public Class Student { 
    public String name;
    public String id;
    //getters & setters for name & id here
}
Run Code Online (Sandbox Code Playgroud)

  • 糟糕的做法 - 这破坏了封装。 (3认同)

krm*_*007 5

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


mat*_*uez 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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Pir*_*ate 5

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

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

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

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

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

谢谢。