0

I'm trying to convert a JSON object to POJOs, and ideally I would have a list of objects (of collection's) in my cluster object. However the JSON schema doesn't use a list, it uses a map of the collection name, which aren't known and might change. Is there a way to convert this to a list of POJOs using GSON?

The JSON in question:

{
  "responseHeader":{
    "status":0,
    "QTime":333},
  "cluster":{
    "collections":{
      "collection1":{
        "shards":{
          "shard1":{
            "range":"80000000-ffffffff",
            "state":"active",
            "replicas":{
              "core_node1":{
                "state":"active",
                "core":"collection1",
                "node_name":"127.0.1.1:8983_solr",
                "base_url":"http://127.0.1.1:8983/solr",
                "leader":"true"},
              "core_node3":{
                "state":"active",
                "core":"collection1",
                "node_name":"127.0.1.1:8900_solr",
                "base_url":"http://127.0.1.1:8900/solr"}}},
          "shard2":{
            "range":"0-7fffffff",
            "state":"active",
            "replicas":{
              "core_node2":{
                "state":"active",
                "core":"collection1",
                "node_name":"127.0.1.1:7574_solr",
                "base_url":"http://127.0.1.1:7574/solr",
                "leader":"true"},
              "core_node4":{
                "state":"active",
                "core":"collection1",
                "node_name":"127.0.1.1:7500_solr",
                "base_url":"http://127.0.1.1:7500/solr"}}}},
        "maxShardsPerNode":"1",
        "router":{"name":"compositeId"},
        "replicationFactor":"1",
        "znodeVersion": 11,
        "autoCreated":"true",
        "configName" : "my_config",
        "aliases":["both_collections"]
      }
    },
    "aliases":{ "both_collections":"collection1,collection2" },
    "roles":{
      "overseer":[
        "127.0.1.1:8983_solr",
        "127.0.1.1:7574_solr"]
    },
    "live_nodes":[
      "127.0.1.1:7574_solr",
      "127.0.1.1:7500_solr",
      "127.0.1.1:8983_solr",
      "127.0.1.1:8900_solr"]
  }
}
Benedict
  • 7
  • 2
  • is there any way you could do some JS preprocessing? that would make this a whole lot easier, as shown [here](https://stackoverflow.com/questions/38824349/convert-object-to-array-in-javascript) If not, you could convert it into a Map and do the appropriate conversions/casts within Java, as shown [here](https://stackoverflow.com/questions/2779251/how-can-i-convert-json-to-a-hashmap-using-gson) – David Culbreth Aug 17 '18 at 14:02
  • That would be ideal, but I would have to do it in Java which seems like more trouble than its worth. – Benedict Aug 17 '18 at 14:26

2 Answers2

0

You might use a TypeAdapter to have your object converted to a list of objects, or just get all objects inside cluster into a JsonArray and then parse it to a List<Collection>, something like this:

JsonArray jsonArr = new JsonArray();

JsonObject fullObj = new GsonBuilder().create().fromJson(jsonStr, JsonObject.class);
fullObj.getAsJsonObject("cluster")
    .entrySet()
    .forEach(col -> jsonArr.add(col.getValue()));

List<Collection> collections = gson.fromJson(jsonArr.toString(), Collection.class);
Philip
  • 319
  • 5
  • 13
  • Unfortunately, this mismatch happens at the `collection` level and at the `shard` level so I would have to go pretty far down in order to do this. Ideally there would be some sort of fix that would do both at the same time. – Benedict Aug 17 '18 at 14:26
  • @Benedict Can you reformat that json to be sent in a way that makes it easy for you to proccess? – Philip Aug 17 '18 at 14:34
0

I recommend you could build the POJO models, and then do the conversion after you have imported the data.

stackoverflow/model/CoreNode.java:

package stackoverflow.model;

/**
 * CoreNode
 */
public class CoreNode {

    private String state;
    private boolean leader;
    private String core;
    private String node_name;
    private String base_url;

    public CoreNode() {
        super();
    }

    public String getState() {
        return this.state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public boolean getLeader() {
        return this.leader;
    }

    public void isLeader(boolean leader) {
        this.leader = leader;
    }

    public String getCore() {
        return this.core;
    }

    public void setCore(String core) {
        this.core = core;
    }

    public String getNode_name() {
        return this.node_name;
    }

    public void setNode_name(String node_name) {
        this.node_name = node_name;
    }

    public String getBase_url() {
        return this.base_url;
    }

    public void setBase_url(String base_url) {
        this.base_url = base_url;
    }

}

stackoverflow/model/Shard.java:

package stackoverflow.model;

import java.util.Map;

/**
 * Shard
 */
public class Shard {

    private String range;
    private String state;
    private Map<String, CoreNode> replicas;

    public Shard() {
        super();
    }

    public String getRange() {
        return this.range;
    }

    public void setRange(String range) {
        this.range = range;
    }

    public String getState() {
        return this.state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public List<CoreNode> getReplicas() {
        return this.replicas;
    }

    public void setReplicas(List<CoreNode> replicas) {
        this.replicas = replicas;
    }

}

then in your main function, use a Map<String, Shard> structure for each collection. (and then a Map<String, Map<String, Shard>> for the genericcollections` structure)

Then, whichever map you wanted as a list, you can just do (in the case of Shards)

new ArrayList<CoreNode>(replicas.values());

David Culbreth
  • 2,610
  • 16
  • 26