2017-06-27 146 views
2

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

这是我的JSON例子:

{ 
    "nodes": { 
     "12131231231231241": { 
       "gToken": { 
        "token": "AABBCCDDEEFF99001122334455667788" 
      }, 
      "objects": { 
       "WATER_CONTROL_1": "0" 
      } 
     }, 
     "7682642342432423": { 
       "userAuthentication": { 
        "userEmail": "[email protected]", 
        "userPassword": "userPassword" 
      }, 
      "objects": { 
       "LIGHT_1_CONTROL": "1" 
      } 
     } 
    } 
} 

如果你能看到nodes对象是动态的。在他里面我可以有很多物品(在我的例子中,我把两个,代表121312312312312417682642342432423)。在每个项目中,认证方法可以不同(通过令牌,通过电子邮件/密码),并且在对象内部项目中,我也可以有很多不同的动态项目。

将部分发送到我的c + +服务器,解析JSON和做所有验证(例如验证)已经完成和工作(我测试这个JSON的例子在C + +字符串内,编码为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 - (尽量使用舍甫琴科Rymar的例子)

我尝试模拟这个JSON:

{ 
    "nodes": { 
     "1317055040393017962": { 
      "userAuthentication": { 
       "userEmail": "[email protected]", 
       "userPassword": "rr123" 
      } 
     } 
    } 
} 

我的请求类: 公共类MonitorControlGetRequestArgs实现SerializableJSON { 私人最终static String nodeTemplate =“\”%s \“:%s”; 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; 
     } 
    } 
} 

EDIT 2

我会尽量解释更好,我相信我没有完全明确。我的应用程序java是一个将json发送到我的C++服务器的REST应用程序。在我的服务器中,我收到了json,我做了解析,我做了验证,操作等等,然后返回到我的java客户端,json中的响应。

例如,假设我的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": "[email protected]", 
        "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 -

我实现这个代码,我几乎能生产所有我需要的结构。我使用的是同样的。

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": "[email protected]", 
       "userPassword": "userPassword" 
      } 
     }, 
     "objects": { 
      "aa": "aaaaaaaaaaaaa", 
      "bbbbbbb": "bbbbb", 
      "ccdd": "ccddccdd" 
     } 
    } 
} 

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

{ 
    "nodes": { 
     "7682642342432423": { 
      "authenticationMethod": { 
       "userAuthentication": { 
        "userEmail": "[email protected]", 
        "userPassword": "userPassword" 
       } 
      }, 
      "objects": { 
       "0": "Hammersmith & City", 
       "1": "Circle", 
       "dasd": "dasda" 
      } 
     } 
    } 
} 

注:对象是一张地图,这样我就可以把我想要的对象的字符串数/字符串数。知道我需要做些什么来支持以前的JSON与7682642342432423,12131231231231241,等等,等等。

编辑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": "[email protected]", 
        "userPassword": "userPassword" 
       } 
      }, 
      "objects": { 
       "aa": "aaaaaaaaaaaaa", 
       "bbbbbbb": "bbbbb", 
       "ccdd": "ccddccdd" 
      } 
     }, 
     "777777777777777": { 
      "authenticationMethod": { 
       "userAuthentication": { 
        "userEmail": "[email protected]", 
        "userPassword": "userPassword" 
       } 
      }, 
      "objects": { 
       "aa": "aaaaaaaaaaaaa", 
       "bbbbbbb": "bbbbb", 
       "ccdd": "ccddccdd" 
      } 

     } 
    } 
} 
+0

你可以编辑这个,并在顶部放置一个句子,说明你的问题是什么?目前尚不清楚你要求什么。 – JeffUK

+0

如果'nodes'数组中有不同的对象,那么你必须为所有的对象类型定义通用接口(或基类)。然后实现JSON容器类,其中'List nodes = new ArrayList()'字段。然后填充您需要的所有对象的列表,并将其序列化为您期望的JSON字符串。 –

+0

无关:请不要在明文中发送密码 – JonK

回答

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","[email protected]"), 
        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":"[email protected]","userPassword":"userPassword"},"objects":{"WATER_CONTROL_1":"0","WATER_CONTROL_2":"1"}}}} 

漂亮的看法是:enter image description here

注意:本实施例中使用的构造来构建复杂的结构,但我强烈推荐使用助洗剂对于这样的情况下图案。代码会更清晰和更好。

+0

所以如果你不知道你的数据或大小的确切值等,这种方法并不重要。只需用类似的方式使用你的数据结构来构建你的'NodeArray'。 (或者将其改为使用生成器模式) –

+0

感谢您的示例。我想我明白你的代码。在你的代码中,你手动输入了内容(12131231231231241等等)。但是它可能创建没有手动内容的nodeArray?我认为它的这一部分,我有一些doubs或问题 – RMRMaster

+0

在我放在这篇文章中的类示例(MonitorControlRequestGet)中,在fromStringJson()函数中,我返回一个新的gson与我的类的对象 – RMRMaster

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

+0

哇,感谢这篇文章。我真的认为它可以帮助我。 您可以在我的作品中添加“手动”“user-1”和“user-2”..因为在我的情况下,我永远不知道用户在主体请求中发送了什么“关键” – RMRMaster

+0

是的,您可以添加任何“对象”,它将起作用。很高兴这有助于你。 –

+0

好的谢谢。我现在将看到你的榜样。真的很感谢;)如果我有一些怀疑我写。 – RMRMaster