【问题标题】:Convert JSON to POJO having Json property as jsonObject having diffrent property将 JSON 转换为具有 Json 属性的 POJO 作为具有不同属性的 json 对象
【发布时间】:2020-10-08 06:58:01
【问题描述】:

我有新要求,我正在创建具有动态请求(操作)的 REST API,我想将该 JSON 请求转换为 POJO,我知道如何将 JSON 转换为密钥相同的 POJO,但不知道该怎么做当对象上有不同的内容时。

我的 Json 如下。

{
  "name":"Workflow",
  "actions": [
    {
      "name": "EDIT_PROPERTY",
      "payload": {
        "name": "city",
        "value": "Pune"
      }
    },
    {
      "name":"SEND_EMAIL",
      "payload":{
        "from":"no-reply@yaho.com",
        "to":"alpesh@yahoo.com",
        "subject":"Try email",
        "body":"content"
      }
    },
    {
      "name":"CREATE_TASK",
      "payload":{
        "user":1,
        "type":"call",
        "status":"open",
        "note":"This is  note content"
      }
    }
  ]
}

正如您所见,动作是一组具有名称和有效负载的对象,现在有效负载具有不同的字段,我有预定义的名称。如您所见,每个有效载荷都有预定义的键。

我想把它转换成类似 POJO 的东西

class Workflow{
    String name;
    Set<Action> actions;
}

class Action {
    String name;
    //What to add as payload
}

谢谢

阿尔佩什

【问题讨论】:

  • 可以将有效负载存储为 Map ?
  • 但是当我使用 Object 时,它不是类型安全的。
  • @Alpesh Jikadra 您使用了哪个 JSON 库?我用Jackson (JDK 1.8) 对其进行了测试,以将字段payload 反序列化为Map&lt;String, Object&gt;,正如@SKumar 评论的那样,它工作正常,没有任何错误。
  • 您对 Map 是否满意,或者您想保留数据类型?
  • @SKumar,是的,我想保留数据类型。

标签: java json jackson fasterxml


【解决方案1】:

这是你可以做的:

JSON 到 POJO 模型:

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Event {
    public String name;
    public List<Action> actions;


    @Data
    public static class Action {
        public String name;
        Map<String, Object> payload;
    }


}

public class TestJson {

    private static String json = "{\n" +
            "  \"name\":\"Workflow\",\n" +
            "  \"actions\": [\n" +
            "    {\n" +
            "      \"name\": \"EDIT_PROPERTY\",\n" +
            "      \"payload\": {\n" +
            "        \"name\": \"city\",\n" +
            "        \"value\": \"Pune\"\n" +
            "      }\n" +
            "    },\n" +
            "    {\n" +
            "      \"name\":\"SEND_EMAIL\",\n" +
            "      \"payload\":{\n" +
            "        \"from\":\"no-reply@yaho.com\",\n" +
            "        \"to\":\"alpesh@yahoo.com\",\n" +
            "        \"subject\":\"Try email\",\n" +
            "        \"body\":\"content\"\n" +
            "      }\n" +
            "    },\n" +
            "    {\n" +
            "      \"name\":\"CREATE_TASK\",\n" +
            "      \"payload\":{\n" +
            "        \"user\":1,\n" +
            "        \"type\":\"call\",\n" +
            "        \"status\":\"open\",\n" +
            "        \"note\":\"This is  note content\"\n" +
            "      }\n" +
            "    }\n" +
            "  ]\n" +
            "}";

    @SneakyThrows
    public static void main(String[] args) {
        ObjectMapper objectMapper = new ObjectMapper();
        Event event = objectMapper.readValue(json, Event.class);
        System.out.println(event);

    }


}

调试时,您会注意到我们的对象已被相应地填充:

【讨论】:

  • 这样,我可能会在 Payload 类下添加太多字段,而其他实体不需要。即 EDIT_PROPERTY 类型。将来我也可能有新类型的有效载荷来执行新操作。
  • @AlpeshJikadra 好的,在这种情况下,我已将有效负载更新为地图,即 Map 有效负载;还更新了答案,并且没有任何问题。
  • 代替 Map,我可以使用某种继承,以便可以使用基类代替 Map 吗?
【解决方案2】:

嗯,一般来说,我更喜欢任何不涉及组件注释的解决方案。这是我个人的偏好,因为消除constructors 和方法parameters 通常是一件非常头疼的事情。这是基于 1999 - 2006 年的 Java 编程经验。如果您需要动态生成类和constructors 或getters,那么您可以轻松忽略或删除此答案。对我来说,JSON Parsing 是现在的练习。

在这个发布的答案中,我使用了较旧的 Java JSON 库,其 JavaDoc 可以在此处查看:javax.json.*。这是我的解决方案。它需要/期望你写:

  • 您自己的 toString() 方法用于您的 JSON 数据类
  • 您自己的检索操作

以下代码有输出,包含在本文末尾。通常我会包含很多代码文档。但是,当代码严格解析数据时,代码本身通常非常清晰,以至于更多的 cmets 会使 retrieve 和 toString() 变得混乱操作,所以我保持原样。

import java.util.*;
import javax.json.*;
import java.io.*;

public class Messages
{
    public abstract static class Action
    {
        public final String name;
        public Action(String name) { this.name=name; }
    }

    public static class EditProperty extends Action
    {
        public final String propName, propValue;

        public EditProperty(String name, String value)
        { super("EDIT_PROPERTY"); this.propName=name; this.propValue=value; }

        public String toString()
        { 
            return 
                "Action:   " + name         + '\n' + 
                "Name:     " + propName     + '\n' +
                "Value:    " + propValue    + '\n';
        }
    }

    public static class SendEmail extends Action
    {
        public final String from, to, subject, body;

        public SendEmail(String from, String to, String subject, String body)
        { super("SEND_EMAIL"); this.from=from; this.to=to; this.subject=subject; this.body=body; }

        public String toString()
        {
            return
                "Action:   "    + name      + '\n' +
                "From:     "    + from      + '\n' +
                "To:       "    + to        + '\n' +
                "Subject:  "    + subject   + '\n' +
                "Body:     "    + body      + '\n';
        }
    }

    public static class CreateTask extends Action
    {
        public final int user;
        public final String type, status, note;

        public CreateTask(int user, String type, String status, String note)
        { super("CREATE_TASK"); this.user=user; this.type=type; this.status=status; this.note=note; }

        public String toString()
        {
            return
                "Action:   " + name     + '\n' +
                "User:     " + user     + '\n' +
                "Type:     " + type     + '\n' +
                "Status:   " + status   + '\n' +
                "Note:     " + note     + '\n';
        }
    }

    public static void main(String[] argv) throws IOException
    {
        Vector<Action>  actions     = new Vector<>();
        Reader          r           = new FileReader("in.json");

        JsonArray       actionList  = Json
            .createReader(r)
            .readObject()
            .getJsonArray("actions");

        for (JsonObject actionObj : actionList.getValuesAs(JsonObject.class))
        {
            JsonObject  payload = actionObj.getJsonObject("payload");
            Action      action  = null;

            switch (actionObj.getString("name"))
            {
                case "EDIT_PROPERTY"    :   action = new EditProperty(
                                                payload.getString("name"),
                                                payload.getString("value")
                                            ); break;
                case "SEND_EMAIL"       :   action = new SendEmail(
                                                payload.getString("from"),
                                                payload.getString("to"),
                                                payload.getString("subject"),
                                                payload.getString("body")
                                            ); break;
                case "CREATE_TASK"      :   action = new CreateTask(
                                                payload.getInt("user"),
                                                payload.getString("type"),
                                                payload.getString("status"),
                                                payload.getString("note")
                                            ); break;
            }
            
            actions.add(action);
        }
        
        for (Action action : actions) System.out.println(action);
    }
}

上面的类和内部类在命令行调用时会产生这个输出:

@cloudshell:~$ java Messages 
Action:   EDIT_PROPERTY
Name:     city
Value:    Pune

Action:   SEND_EMAIL
From:     no-reply@yaho.com
To:       alpesh@yahoo.com
Subject:  Try email
Body:     content

Action:   CREATE_TASK
User:     1
Type:     call
Status:   open
Note:     This is  note content

【讨论】:

    【解决方案3】:

    您显示的 JSON 实际上是一种对象类型的列表; 具体来说,payload 只是 String 到 Object 的 Map。

    解析 JSON 后, 您的代码将需要处理每个“不同”的有效负载类型 基于负载类型。

    这里是一些示例代码:

    public class BlamMessage
    {
        private String name;
        private Map<String, Object> payload;
    
        ...
    }
    
    public class MessageHolder
    {
        @JsonProperty("actions")
        private List<BlamMessage> messageList;
    
        private String name;
    
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 2015-09-22
      • 1970-01-01
      • 2016-12-28
      • 1970-01-01
      • 2021-07-23
      • 2021-11-17
      • 2020-02-02
      • 2020-12-17
      • 1970-01-01
      相关资源
      最近更新 更多