构建动态JSON

时间:2017-06-27 10:09:53

标签: java json gson

我试图在java中构建动态json请求以发送到我的c ++服务器。我正在使用GSON库。

这是我的json示例:

{
    "nodes": {
        "12131231231231241": {
                "gToken": {
                    "token": "AABBCCDDEEFF99001122334455667788"
            },
            "objects": {
                "WATER_CONTROL_1": "0"
            }
        },
        "7682642342432423": {
                "userAuthentication": {
                    "userEmail": "user@mail.com",
                    "userPassword": "userPassword"
            },
            "objects": {
                "LIGHT_1_CONTROL": "1"
            }
        }
    }
}

如果您可以看到nodes对象是动态的。在他的内心,我可以有很多项目(在示例中我放了两个,代表121312312312312417682642342432423)。在每个项目中,身份验证方法可以是不同的(通过令牌,通过电子邮件/密码)和内部对象项目,我也可以有很多不同的动态项目。

要发送到我的c ++服务器的部分,解析JSON并进行所有验证(例如验证)已经完成并正常工作(我在c ++字符串中测试这个json示例,编码为json并进行解析,得到所有项目等)。

所以我的问题是构建我的类来发送带有一些结构的请求来对应这个动态的json。

我已经实现了一些其他类来将json发送到我的服务器及其工作,因为我已经知道了json的预期,而在其他情况下,json有静态/固定的内容。

我对这个动态json的课程:

public class MonitorControlGetRequestArgs implements SerializableJSON {
    Nodes nodes;

    public MonitorControlGetRequestArgs()   {
        nodes = new Nodes();
    }

    static class Nodes{
        public Nodes(){
        }
    }


    public static MonitorControlGetRequestArgs fromStringJson(String data){
        try {   
        Gson gson = new Gson();
            return gson.fromJson(data, MonitorControlGetRequestArgs.class);
        }
        catch(Exception e){
            return null;
        }
    }

    public static MonitorControlGetRequestArgs fromBytesJson(byte[] data){
        if (data == null)
            return null;
        try {
            String str = new String(data, "utf-8");
            return fromStringJson(str); 
        }
        catch (Exception e) {
            return null;
        }
    }

    @Override
    public String toJsonString(){
        try{
            Gson gson = new Gson();
            return gson.toJson(this);
        }
        catch(Exception e){
            return null;
        }
    }

    @Override
    public byte[] toJsonBytes(){
        try {
            return this.toJsonString().getBytes("utf-8");
        }
        catch (Exception e){
            return null;
        }
    }
}

我创建了一个static class Nodes空来向您展示。在我的服务器c ++中,我以json格式接收项nodes,但现在我有很多疑问如何在nodes内构建结构以对应于我的动态json。

我希望你理解我的怀疑。如果你不明白的话告诉我。

编辑1 - (尝试使用Andriy Rymar的例子)

我尝试模拟这个json:

{
    "nodes": {
        "1317055040393017962": {
            "userAuthentication": {
                "userEmail": "rr@rr.com",
                "userPassword": "rr123"
            }
        }
    }
}

我的要求类:     公共类MonitorControlGetRequestArgs实现SerializableJSON     {         private final static String nodeTemplate =" \"%s \":%s&#34 ;;         List nodes = new ArrayList<>();

    public MonitorControlGetRequestArgs(UserAuthentication userAuthentication)
    {
        JsonData jsonData = new JsonData();
        jsonData.addNode(new Node("1317055040393017962", new NodeObject(userAuthentication)));
    }

    static class Node 
    {
        private final String nodeName;
        private final Object nodeBody;

        public Node(String nodeName, Object nodeBody) {
          this.nodeName = nodeName;
          this.nodeBody = nodeBody;
        }

        public String getNodeName() {
          return nodeName;
        }

        public Object getNodeBody() {
          return nodeBody;
        }
    }

    static class JsonData {

        List<Node> nodes = new ArrayList<>();

        public void addNode(Node node){
          nodes.add(node);
        }
      }

    static class NodeObject
    {
        UserAuthentication userAuthentication;

        public NodeObject(UserAuthentication userAuthentication)
        {
            this.userAuthentication = userAuthentication;
        }
    }

    public static MonitorControlGetRequestArgs fromStringJson(String data)
    {
        try
        {
            Gson gson = new Gson();
            return gson.fromJson(data, MonitorControlGetRequestArgs.class);
        }
        catch(Exception e)
        {
            return null;
        }
    }

    public static MonitorControlGetRequestArgs fromBytesJson(byte[] data)
    {
        if (data == null) return null;
        try 
        {
            String str = new String(data, "utf-8");
            return fromStringJson(str); 
        }
        catch (Exception e) 
        {
            return null;
        }
    }

    @Override
    public String toJsonString()
    {
        try
        {
            Gson gson = new Gson();
            return gson.toJson(this);
        }
        catch(Exception e)
        {
            return null;
        }
    }

    @Override
    public byte[] toJsonBytes()
    {
        try 
        {
            return this.toJsonString().getBytes("utf-8");
        }
        catch (Exception e)
        {
            return null;
        }
    }
}

编辑2

我会尝试更好地解释,我相信我并不是完全明确的。我的应用程序java是一个REST应用程序,它将json发送到我的c ++服务器。在我的服务器中,我收到了json,我进行了解析,我进行了验证,操作等,并在json中返回我的java客户端响应。

例如,假设我的json请求体(例如创建一个新用户)是这样的:

{
    "userInformation": {
        "name": "user name",
        "age": 33
    }
}

为此,我不知道该怎么做(我已经实现了很多非常相似的请求)。我可以创建一个这样的静态类:

static class UserInfo
{
   String name;
   String age;

   public UserInfo(String name, String age)
   {
     this.name = name;
     this.age = age;
   }
}

在请求类中(非常类似于我之前复制的类 - MonitorControlGetRequestArgs)我为UserInfo创建了一个新实例

UserInfo userInformation = new UserInfo (name, age)

在这种情况下,它很容易因为请求json体是静态的。我现在已经有一个userInformation部分,里面有一个名字和年龄。要创建一个包含userInfo的列表(例如,同时创建多个用户),我已经实现了这样的事情。

但是现在,对于这个特例,我有这个json:

{
    "nodes": {
        "12131231231231241": {
                "gToken": {
                    "token": "AABBCCDDEEFF99001122334455667788"
            },
            "objects": {
                "WATER_CONTROL_1": "0"
            }
        },
        "7682642342432423": {
                "userAuthentication": {
                    "userEmail": "user@mail.com",
                    "userPassword": "userPassword"
            },
            "objects": {
                "LIGHT_1_CONTROL": "1"
                 "LIGHT_3_CONTROL": "0"
            }
        }
    }
}

所以在这种情况下我有一些问题。在这些例子中,我放了两个项目(12131231231231241,7682642342432423),但用户可以发送更多(3,4,5,50,100)。在另一方面nodes里面我有两个部分(12131231231231241,7682642342432423),但是这个数字是我在我的应用程序中使用的一些ID,我永远不会知道用户将放置的ID。在最后一个示例(userInformation)中,它很简单,因为我创建了一个userInformation部分因为我已经知道用户总是放置这个部分,所以它是静态的。在这些新的json请求中,我不知道,因为我现在从来没有放过什么价值,我只知道这是一个字符串。身份验证方法我没有创建问题。但我期望的其他问题是在对象部分,因为用户可以放置很多对象,我永远不知道什么是密钥(在userInformation我知道密钥总是名称和年龄例子,只退出这两个键,我这些新的情况我不知道什么是键,他放的键/值的数量是多少。

编辑3 -

我实现了这个代码,我几乎可以生成我需要的所有结构。我同样使用gson。

Nodes nodes;

public MonitorControlGetRequestArgs(String userEmail, String userPassword, Map <String,String> objects)
{
    nodes = new Nodes(userEmail, userPassword, objects);
}

static class Nodes
{
    AuthenticationMethod authenticationMethod;
    Map <String,String> objects;

    public Nodes(String userEmail, String userPassword, Map <String,String> objects)
    {
        authenticationMethod = new AuthenticationMethod(userEmail, userPassword);
        this.objects = objects;
    }
}

结果json:

{
    "nodes": {
        "authenticationMethod": {
            "userAuthentication": {
                "userEmail": "user@mail.com",
                "userPassword": "userPassword"
            }
        },
        "objects": {
            "aa": "aaaaaaaaaaaaa",
            "bbbbbbb": "bbbbb",
            "ccdd": "ccddccdd"
        }
    }
}

知道我只需要添加一些结构来支持这个json:

{
    "nodes": {
        "7682642342432423": {
            "authenticationMethod": {
                "userAuthentication": {
                    "userEmail": "user@mail.com",
                    "userPassword": "userPassword"
                }
            },
            "objects": {
                "0": "Hammersmith & City",
                "1": "Circle",
                "dasd": "dasda"
            }
        }
    }
}

注意:对象是一个地图,所以我可以把我想要的对象数字串/字符串。知道我需要用7682642342432423,12131231231231241等来支持以前的json。

编辑4 - 最终

Map <String, Obj> nodes;

    public MonitorControlGetRequestArgs(Map <String, Obj> nodes)
    {
        this.nodes = nodes; 
    }

    static class Obj
    {

        AuthenticationMethod authenticationMethod;
        Map <String,String> objects;

        public Obj(String userEmail, String userPassword, Map <String,String> objects)
        {
            authenticationMethod = new AuthenticationMethod(userEmail, userPassword);
            this.objects = objects;
        }


    }

Json到达我的服务器(就像我想要的那样)

{
    "nodes": {
        "12131231231231241": {
            "authenticationMethod": {
                "userAuthentication": {
                    "userEmail": "user@mail.com",
                    "userPassword": "userPassword"
                }
            },
            "objects": {
                "aa": "aaaaaaaaaaaaa",
                "bbbbbbb": "bbbbb",
                "ccdd": "ccddccdd"
            }
        },
        "777777777777777": {
            "authenticationMethod": {
                "userAuthentication": {
                    "userEmail": "user@mail.com",
                    "userPassword": "userPassword"
                }
            },
            "objects": {
                "aa": "aaaaaaaaaaaaa",
                "bbbbbbb": "bbbbb",
                "ccdd": "ccddccdd"
            }

        }
    }
}

2 个答案:

答案 0 :(得分:0)

以下是使用Gson所需内容的示例。但是如果您想使用其他东西,例如OrgJson,那么代码将更清晰,没有String模板。

public class ForTestApplication {
  private final static String nodeTemplate = "\"%s\":%s";

  public static void main(String[] args) {

    JsonData jsonData = new JsonData();

    jsonData.addNode(new Node("user-1", new TestObject(62, "James", "Gosling")));
    jsonData.addNode(new Node("user-2", new TestObject(53, "James", "Hetfield")));

    System.out.println(jsonData.toJSONStirng());
  }


  static class JsonData {

    List<Node> nodes = new ArrayList<>();

    public void addNode(Node node){
      nodes.add(node);
    }

    public String toJSONStirng() {
      Gson gson = new Gson();

      return nodes.stream()
          .map(node -> String.format(nodeTemplate, node.getNodeName(), gson.toJson(node.getNodeBody())))
          .collect(Collectors.joining(",", "{", "}"));
    }
  }

  static class Node {
      private final String nodeName;
      private final Object nodeBody;


    public Node(String nodeName, Object nodeBody) {
      this.nodeName = nodeName;
      this.nodeBody = nodeBody;
    }

    public String getNodeName() {
      return nodeName;
    }

    public Object getNodeBody() {
      return nodeBody;
    }
  }

  static class TestObject {
    private int age;
    private String firstName;
    private String lastName;

    public TestObject(int age, String firstName, String lastName) {
      this.age = age;
      this.firstName = firstName;
      this.lastName = lastName;
    }

    public int getAge() {
      return age;
    }

    public void setAge(int age) {
      this.age = age;
    }

    public String getFirstName() {
      return firstName;
    }

    public void setFirstName(String firstName) {
      this.firstName = firstName;
    }

    public String getLastName() {
      return lastName;
    }

    public void setLastName(String lastName) {
      this.lastName = lastName;
    }
  }

}

输出:

{"user-1":{"age":62,"firstName":"James","lastName":"Gosling"},"user-2":{"age":53,"firstName":"James","lastName":"Hetfield"}}

漂亮的观点: enter image description here

答案 1 :(得分:0)

以下是上一个示例中的改进代码,它更灵活,具有更好的序列化机制:

public class ForTestApplication {

  public static void main(String[] args) {

    NodeArray jsonContainer = new NodeArray(
        new Node("nodes",  new NodeArray(
            new Node("12131231231231241", new NodeArray(
                new Node("gToken",
                    new Node("token", "AABBCCDDEEFF99001122334455667788")),
                new Node("objects", new NodeArray(
                    new Node("WATER_CONTROL_1", "0"),
                    new Node("WATER_CONTROL_2", "1")
                )))),
            new Node("7682642342432423", new NodeArray(
                new Node("userAuthentication", new NodeArray(
                    new Node("userEmail","user@mail.com"),
                    new Node("userPassword","userPassword")
                )),
                new Node("objects", new NodeArray(
                    new Node("WATER_CONTROL_1", "0"),
                    new Node("WATER_CONTROL_2", "1")
                ))
            ))
        )));

    System.out.println(jsonContainer.toJSONString());
  }

}

class NodeArray {
  private static final String NODE_TEMPLATE = "\"%s\":%s";
  private static final Gson gson = new Gson();

  private List<Node> nodes = new ArrayList<>();

  public NodeArray(Node... nodes){
    addNode(nodes);
  }

  public void addNode(Node... node){
    nodes.addAll(Arrays.asList(node));
  }

  public String toJSONString() {

    return nodes.stream()
        .map(node -> String.format(NODE_TEMPLATE, node.getNodeName(), getNodeBodyAsJSON(node)))
        .collect(Collectors.joining(",", "{", "}"));
  }

  private String getNodeBodyAsJSON(Node node) {
    if (node.getNodeBody() instanceof NodeArray) {
      return ((NodeArray) node.getNodeBody()).toJSONString();
    }
    return gson.toJson(node.getNodeBody());
  }

}

class Node {
  private final String nodeName;
  private final Object nodeBody;

  public Node(String nodeName, Object nodeBody) {
    this.nodeName = nodeName;
    this.nodeBody = nodeBody;
  }

  public String getNodeName() {
    return nodeName;
  }

  public Object getNodeBody() {
    return nodeBody;
  }
}

此类申请的输出是:

{"nodes":{"12131231231231241":{"gToken":{"nodeName":"token","nodeBody":"AABBCCDDEEFF99001122334455667788"},"objects":{"WATER_CONTROL_1":"0","WATER_CONTROL_2":"1"}},"7682642342432423":{"userAuthentication":{"userEmail":"user@mail.com","userPassword":"userPassword"},"objects":{"WATER_CONTROL_1":"0","WATER_CONTROL_2":"1"}}}}

漂亮的观点是:enter image description here

注意:此示例使用构造函数构建复杂的结构,但我强烈建议在这种情况下使用构建器模式。代码将更清晰,更好。