【问题标题】:Jackson object mapper returns 0 for integer and null for stringJackson 对象映射器为整数返回 0,为字符串返回 null
【发布时间】:2020-07-31 19:06:05
【问题描述】:

我有一个结构列表,我将从 restEndpoint 获取它,我必须将它映射到 Java 对象列表。但在这个项目中,我刚刚给出了一个 json 格式的字符串作为输入。当我尝试在我的对象中获取字符串数据时,我总是得到 null,而当我获取整数时,我总是得到 0。

我认为 objectMapper 无法将字符串 json 映射到对象。但我没有得到任何错误。

结果 = mapper.readValue(json, new TypeReference>() {});没有工作。也许是一些配置或版本问题?>

我的对象

public class myObject {

    @JsonProperty("userID")
    private int userID;
    @JsonProperty("id")
    private int id;
    @JsonProperty("title")
    private String title;
    @JsonProperty("body")
    private String body;
    @JsonCreator
    public myObject() {
    }
    @JsonProperty("userID")
    public int getUserId() {
        return userID;
    }
    @JsonProperty("userID")
    public void setUserId(int userId) {
        this.userID = userId;
    }
    @JsonProperty("id")
    public int getId() {
        return id;
    }
    @JsonProperty("id")
    public void setId(int id) {
        this.id = id;
    }
    @JsonProperty("title")
    public String getTitle() {
        return title;
    }
    @JsonProperty("title")
    public void setTitle(String title) {
        this.title = title;
    }
    @JsonProperty("body")
    public String getBody() {
        return body;
    }
    @JsonProperty("body")
    public void setBody(String body) {
        this.body = body;
    } 

我的映射器函数是这样的

ObjectMapper mapper = new ObjectMapper();
          mapper.setVisibilityChecker(mapper.getSerializationConfig().getDefaultVisibilityChecker()
                .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
 try {
            //List<myObject> mstCodes = null;
            String json = "[{\"userID\":1,\"id\":\"1\",\"title\":\"IT\",\"body\":\"123234\"},{\"userID\":0,\"id\":\"2\",\"title\":\"Accounting\",\"body\":\"adsfnsdf\"}]";
            List<myObject> mstCodes = mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, myObject.class));
            System.out.println(mstCodes.size());
            System.out.println(mstCodes.get(0));
            System.out.println(mstCodes.get(0).getUserId());
            System.out.println(mstCodes.get(0).getBody());
        } catch (IOException e) {
            System.out.println("Failed serializing response" + e.getMessage());
        }

我收到的上述打印语句的输出是:

2
com.example.varun.testProject$myObject@4e7dc304
0
null

这可能是一个简单的错误,但感谢任何帮助。谢谢。

【问题讨论】:

  • * .withGetterVisibility(JsonAutoDetect.Visibility.NONE) .withSetterVisibility(JsonAutoDetect.Visibility.NONE)* 字面意思是 - 没有 setter 和 getter....
  • 您应该只将@JsonProperty 应用于字段(从getter/setter 中删除它们),然后使用没有可见性规则的默认ObjectMapper mapper = new ObjectMapper(); - 在您的情况下应该可以正常工作,
  • 它几乎肯定不会“返回”它们,而是根本没有将任何东西反序列化到它们中(让它们处于默认状态)。从您的类中删除每一个Jackson 注释,并从您的映射器中删除每一个自定义配置,看看它是否按预期工作。您正在做很多您还不了解的手动配置,所有这些都是不必要的,因为 Jackson 已被调整为默认情况下运行良好。
  • 这显然是我之前的想法。我刚刚写了 ObjectMapper mapper = new ObjectMapper();没有任何可见性规则,也没有 JsonProperty。即使删除所有内容也无法正常工作
  • 一一删除了所有属性。没有任何工作。只需在构造函数中保留 @JsonCreator public myObject() { } 和 @JsonIgnoreProperties(ignoreUnknown = true) public class testProject {

标签: java jackson-databind


【解决方案1】:

出于演示目的,我只是用 Lombok 简化了您的 myObject 类。
我也只是用了一个简单的ObjectMapper
诀窍是使用TypeReference,它采用可以是任何你需要的泛型类型(在你的情况下是List&lt;MyObject&gt;)。

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.List;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
class MyObject {

    @JsonProperty("userID")
    private int userID;

    @JsonProperty("id")
    private int id;

    @JsonProperty("title")
    private String title;

    @JsonProperty("body")
    private String body;

}

public class Demo {

    public static void main(String[] args) {
        final String json = "[{\"userID\":1,\"id\":\"1\",\"title\":\"IT\",\"body\":\"123234\"},{\"userID\":0,\"id\":\"2\",\"title\":\"Accounting\",\"body\":\"adsfnsdf\"}]";
        final ObjectMapper objectMapper = new ObjectMapper();

        try {
            final List<MyObject> results = objectMapper.readValue(json, new TypeReference<List<MyObject>>() {});
            System.out.println(results.size());
            System.out.println(results.get(0).getUserID());
            System.out.println(results.get(0).getBody());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

输出是:

2
1
123234

编辑: 要解决错误No suitable constructor found for type,以下是没有 Lombok 的对象应该是什么样子(但它也是一样的)。您必须提供一个空构造函数和一个全参数构造函数。

@Getter
class MyObject {

    @JsonProperty("userID")
    private int userID;

    @JsonProperty("id")
    private int id;

    @JsonProperty("title")
    private String title;

    @JsonProperty("body")
    private String body;

    public MyObject() {}

    public MyObject(int userID, int id, String title, String body) {}

}

【讨论】:

  • 我之前尝试过,但它不起作用。仍然得到这些结果。 2 0 空。是版本问题吗?
  • 如果您尝试过但没有成功,我认为问题出在您的 myObject 类本身。试着让它变得非常简单。正如其他人所建议的那样,仅在类属性上保留 @JsonProperty 注释。移除构造函数、getter 和 setter 上的注解。
  • 如果我删除@JsonIgnoreProperties(ignoreUnknown = true) 我得到这个错误---> com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "userId" (class com.example.varun .testProject),未标记为可忽略(0 个已知属性:]),如果我从构造函数 @JsonCreator 中删除它我得到这个错误序列化响应失败没有找到适合类型 [简单类型,类 com.example.varun.testProject$MyObject] 的构造函数: 无法从 JSON 对象实例化(需要添加/启用类型信息?)
  • 您应该使用您的实际代码真正编辑您的问题,因为如果您共享一个编辑版本,将很难为您提供帮助。错误 Unrecognized field "userId" 是因为您从调用的服务的 JSON 中收到 userId 属性。但是在您的代码中,您只映射了 userID 属性(请参阅大小写差异)。
【解决方案2】:

您应该使用下面的默认对象映射器:

ObjectMapper objectMapper = new ObjectMapper();

然后使用这个 objectMapper 来实现你想要的。

对于单个对象,您可以使用以下代码 sn-p 通过 JACKSON 将 JSON 映射到您的对象。

YourObject yourObject = (YourObject) mapper.readValue(json, YourObject.class);

最后,正因为如此,您问:ObjectMapper 能够将 JSON 映射到带有 JACKSON 的对象而没有错误。

【讨论】:

  • 我需要它作为对象列表。不只是针对单个对象。
  • 您可以逐个遍历您的列表,每次都将每个映射的对象添加到您的列表中。
【解决方案3】:

这是在 MyObject (Jackson 2.10) 上使用纯 ObjectMapper 而没有冗余注释的工作方式:

public class MyObject {

    private int userID;
    private int id;
    private String title;
    private String body;

    public int  getUserID()           { return userID; }
    public void setUserID(int userID) { this.userID = userID; }

    public int  getId()       { return id; }
    public void setId(int id) { this.id = id; }

    public String getTitle()             { return title; }
    public void   setTitle(String title) { this.title = title; }

    public String getBody()            { return body; }
    public void   setBody(String body) { this.body = body; }

    @Override
    public String toString() {
        return "MyObject [userID=" + userID + ", id=" + id + ", title=" + title + ", body=" + body + "]";
    }
}

public class MyObjectJsonTest {
    public static void main(String...args) throws JsonMappingException, JsonProcessingException {
        String json = "[{\"userID\":1,\"id\":\"1\",\"title\":\"IT\",\"body\":\"123234\"},{\"userID\":0,\"id\":\"2\",\"title\":\"Accounting\",\"body\":\"adsfnsdf\"}]";
        ObjectMapper mapper = new ObjectMapper();
        List<MyObject> list = mapper.readValue(json, new TypeReference<List<MyObject>>(){});
        System.out.println(list);
    }
}

输出:

[MyObject [userID=1, id=1, title=IT, body=123234], MyObject [userID=0, id=2, title=Accounting, body=adsfnsdf]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-10
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    • 2015-02-12
    • 2015-10-08
    • 2021-02-17
    • 1970-01-01
    相关资源
    最近更新 更多