java - 如何将第三方api中的JSON对象转换为本地POJO

标签 java json deserialization

假设我调用第三方 API 来获取对象 Task,我得到以下 JSON 字符串作为返回:

 {
    "tasks": [
      {
        "id": 1,
        "code": "CODE",
        "description": "Dummy Task",
        "withConfirmation": false,
        "resource": {
          "id": "abcdef12-fe14-57c4-acb5-1234e7456d62",
          "group": "Doctor",
          "firstname": "Toto",
          "lastname": "Wallace",
      },
      {
        "id": 2,
        "code": "CODE",
        "description": "Dummyyy Taaask",
        "withConfirmation": false
      }
    ]
 }

在返回的 json 中,我们有一个任务,可以与资源连接。

在我们的系统中,任务如下:

@JsonAutoDetect
public class Task implements Serializable {

    private Integer id;
    private String code = "BASIC";
    private String description;
    private boolean withConfirmation = false;


    /**
     * CONSTRUCTOR
     */
    public Task() {
    }
    public Integer getId() {
        return id;
    }

    @JsonProperty
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }

    @JsonProperty
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }

    @JsonProperty
    public boolean isWithConfirmation() {
        return withConfirmation;
    }
    public void setWithConfirmation(boolean withConfirmation) {
        this.withConfirmation = withConfirmation;
    }

    public String toString() {...
    }
}

资源看起来像这样:

public class Resource implements Serializable {
    ...

    private String firstname;
    private String lastname;
    private MedicalGroup group; // id + name + description
    private Set<Task> tasks = new HashSet<Task>(0);
    ...
    // getters and setters and toString etc.
    ...
}

因此,除了字段名称之外,主要区别在于任务不包含任何资源,但关系方向相反,这意味着< em>资源可以容纳n任务

对于这种情况,序列化从第三方返回的 json 对象并将其转换/映射到我自己的系统中的 pojo 的最佳方法是什么? 我目前正在阅读 Gson 文档以尝试它,但欢迎任何建议。 该代码必须易于重用,因为多个项目都需要它。

最佳答案

这不是完整的工作代码,因为我不知道你想如何使用 Resource 。 Json 应该创建新资源还是尝试查找已经存在的资源。您将如何从 json 创建 MedicalGroup,因为它没有足够的数据。我本来想在评论中问这个问题,但空间不够。这里是演示如何尝试解决除 Resources to/from json 映射之外的大多数问题。

主要思想是在 @JsonAnyGetter public Map<String, Object> getAdditionalProperties() POJO 中添加 @JsonAnySetter public void setAdditionalProperty(String name, Resource value)Task:

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {

        HashMap<String, Object> map= new HashMap<>();

        // IMPORTANT
        // here we can try to find resource that has this task
        // and export its info to json like this:


        // CHANGE THIS
        Resource res = new Resource();
        res.firstname = "Toto";
        res.lastname = "Wallace";

        // IMPORTANT END

        map.put("resource", res);

        return map;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Resource value) {
        // IMPORTANT
        // Here you have to create or find appropriate Resource in your code
        // and add current task to it
        System.out.println(name+" "+ value );
    }

完整演示:

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.io.Serializable;
import java.util.*;

public class Main3 {
private static String json = "{\n" +
        "    \"tasks\": [\n" +
        "      {\n" +
        "        \"id\": 1,\n" +
        "        \"code\": \"CODE\",\n" +
        "        \"description\": \"Dummy Task\",\n" +
        "        \"withConfirmation\": false,\n" +
        "        \"resource\": {\n" +
        "          \"id\": \"abcdef12-fe14-57c4-acb5-1234e7456d62\",\n" +
        "          \"group\": \"Doctor\",\n" +
        "          \"firstname\": \"Toto\",\n" +
        "          \"lastname\": \"Wallace\"\n" +
        "      }},\n" +
        "      {\n" +
        "        \"id\": 2,\n" +
        "        \"code\": \"CODE\",\n" +
        "        \"description\": \"Dummyyy Taaask\",\n" +
        "        \"withConfirmation\": false\n" +
        "      }\n" +
        "    ]\n" +
        " }";

public static void main(String[] args) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    TasksList tl = mapper.readValue(json, TasksList.class);
    String result = mapper.writeValueAsString(tl);
    System.out.println(result);
}

private static class TasksList {
    @JsonProperty(value = "tasks")
    private List<Task> tasks;
}
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Resource implements Serializable {
    @JsonProperty(value = "firstname")
    private String firstname;
    @JsonProperty(value = "lastname")
    private String lastname;

    // HAVE NO IDEA HOW YOU GONNA MAP THIS TO JSON
    // private MedicalGroup group; // id + name + description
    private Set<Task> tasks = new HashSet<Task>(0);

    @Override
    public String toString() {
        return "Resource{" +
                "firstname='" + firstname + '\'' +
                ", lastname='" + lastname + '\'' +
                ", tasks=" + tasks +
                '}';
    }
}

@JsonAutoDetect
public static class Task implements Serializable {

    private Integer id;
    private String code = "BASIC";
    private String description;
    private boolean withConfirmation = false;

    /**
     * CONSTRUCTOR
     */
    public Task() {
    }
    public Integer getId() {
        return id;
    }

    @JsonProperty
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }

    @JsonProperty
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }

    @JsonProperty
    public boolean isWithConfirmation() {
        return withConfirmation;
    }
    public void setWithConfirmation(boolean withConfirmation) {
        this.withConfirmation = withConfirmation;
    }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {

        HashMap<String, Object> map= new HashMap<>();

        // IMPORTANT
        // here we can try to find resource that has this task
        // and export its info to json like this:
        // CHANGE THIS

        Resource res = new Resource();
        res.firstname = "Toto";
        res.lastname = "Wallace";

        // IMPORTANT END

        map.put("resource", res);

        return map;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Resource value) {
        // IMPORTANT
        // Probably here you have to create or find appropriate Resource in your code
        // and add current task to it
        System.out.println(name+" "+ value );
    }

    @Override
    public String toString() {
        return "Task{" +
                "id=" + id +
                ", code='" + code + '\'' +
                ", description='" + description + '\'' +
                ", withConfirmation=" + withConfirmation +
                '}';
    }
}
}

关于java - 如何将第三方api中的JSON对象转换为本地POJO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36268367/

相关文章:

java - Protocol buffers可以跨语言使用吗

c# - 将 GameObject 转换回通用类型 <T>

java - 如何获取我通过 System.out.println 发送的值?

java - 使用 FlatFileItemReader 读取元素列表

javascript - AJAX 调用并清理 JSON 但语法错误 : missing ; before statement

java - 从JAVA中的sql查询中获取JSON的所有行

java - 我的 Java 程序在计算机上编译,但在网站 URI 上出现运行时错误

java - 接口(interface)和协变返回类型

java - 如何通过jackson JsonGenerator内联对象?

c# - Json.NET 不使用自定义 getter 和不可变类型反序列化属性