2017-06-27 72 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