杰克逊处理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个回答

7

我通过简单地更改我的POJO类的setter和getter方法的签名来解决了这个问题。我所要做的就是将getObject方法更改为与映射器所需的匹配项。在我的情况下,我最初有一个getImageUrl,但JSON数据有一个image_url,这导致了映射器的错误。我将我的setter和getter都更改为getImage_url和setImage_url。


你说得对,如果想要的名称是xxx_yyy, 调用它的方式应该是getXxx_yyy和setXxx_yyy。这很奇怪,但它可行。 - sivi

7

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


6

更改其中之一

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

to

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

----或----

将您的JSON字符串更改为

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

6
我成功的方法是将该属性设为公共属性。

很有帮助!而且类最好设为公共的。 - Сергей

5

这对我来说完全奏效了

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

这似乎只是对许多现有答案的重复。 - undefined

5

将你的类成员设置为public而非private

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

3
不良的实践 - 这破坏了封装性。 - Downhillski
1
我听说过。 - Downhillski
当用户使用您的类时,存在风险,因为这些字段可能会改变内部状态。 - Downhillski

5

您的输入

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

这段文字表明它是一个对象,其中包含一个名为“wrapper”的字段,它是一组学生的集合。因此,我的建议是:

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 数据库将自动将您传递给 DatabaseReference.setValue() 的 Java 对象转换为 JSON,并可以使用 DataSnapshot.getValue() 将 JSON 读入 Java 对象。

在新的 SDK 中,使用 DataSnapshot.getValue() 将 JSON 读入 Java 对象时,默认情况下会忽略 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注释。


5

如果由于某些原因你无法在类中添加 @JsonIgnoreProperties 注解,而你又处于 Jetty 等 Web 服务器/容器内,那么你可以在自定义提供程序中创建和自定义 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;
    }
}

5

就我而言,“@JsonIgnoreProperties(ignoreUnknown = true)”这行代码也没有起作用。

只需要添加以下代码:

@JsonInclude(Include.NON_EMPTY)

Jackson 2.4.0


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