如何构造此JSONObjects的JSON数组

时间:2019-01-03 19:54:31

标签: java json

我有一个必须用Java解决的问题。我在YAML中有一个数据,该数据在此结构中

600450:
  STATE:STATE1
  CITY:CITY1
  ID:1
  CONTACT:1234
600453:
  STATE:STATE1
  CITY:CITY1
  ID:2
  CONTACT:3456
600451:
  STATE:STATE2
  CITY:CITY2 
  ID:3
  CONTACT:2234
.....

我将其转换为JSONObject,但正在努力将其更改为结构应为这种形式的JSONObject对象

{
  STATE1:
        {[
           CITY1:{
                    [{ID:1,CODE:600450,CONTACT:1234}, 
                     {ID:2,CODE:600453,CONTACT:3456}
                    ]
                 },
           CITY2:{
                    [
                      {ID:3,CODE:600451,CONTACT:1234}
                    ]
                 }
        ]}
}

通过使用JSONObject和JSONArray做不同的事情,然后切换到HashMap的HashMap和ArrayList,我几乎损失了一个小时,但我无法获得它! 这是我的尝试,我确定这是荒谬的,我知道如何用Java实现。

3 个答案:

答案 0 :(得分:0)

允许我扮演魔鬼的代言人。

我认为您可能会冒险偏离.yaml中描述的关系。您应该尽量避免在数据模型中嵌入任何特定于应用程序的逻辑,因为您的假设将来可能会使您陷入更棘手的地方。

通常,您应该尊重数据的初始形式,并在运行时处理的灵活性下解释关系或关联的逻辑。否则,您最终将序列化与源不直接相关的数据结构,并且您的假设可能会使您陷入困境。

我怀疑是“真实的” JSON等价物;看起来像这样:

{
  "600450": {
    "STATE": "STATE1",
    "CITY": "CITY1",
    "ID": 1,
    "CONTACT": 1234
  },
  "600453": { ...etc }
}

仍然可以配对这些关系。如果要按城市关联所有对象,则可以先将它们分成箱。您可以通过使用MapString的城市与List s的JSONObject相关联来实现此目的:

// This will be a Map of List of JSONObjects separated by the City they belong to.
final Map<String, List<JSONObject>> mCityBins = new ArrayList();
// Iterate the List of JSONObjects.
for(final JSONObject lJSONObject : lSomeListOfJSONObjects) {
  // Fetch the appropriate bin for this kind of JSONObject's city.
  List<JSONObject> lBin = mCityBins.get(lJSONObject.get("city"));
  // Does the right bin not exist yet?
  if (lBin ==  null) {
    // Create it!
    lBin = new ArrayList();
    // Make sure it is in the Map for next time!
    mCityBins.add(lJSONObject.get("city"), lBin);
  }
  // Add the JSONObject to the selected bin.
  lBin.add(lJSONObject);
}

在处理JSONObject的同时,每当遇到Map中不存在其密钥的城市时,您都可以分配一个新的List<JSONObject>,并在其中添加当前项目List并将其添加到Map中。对于您处理的下一个JSONObject,如果它属于同一城市,则会找到现有的List并将其添加到其中。

一旦将它们分成垃圾箱,生成相应的JSON将很容易!

答案 1 :(得分:0)

当我看到您的git repo时,您只是尝试将第一个Json结构转换为所需的新结构。我必须告诉您,您可能可以直接从YAML文件创建此结构。 因为我没有看到您的第一个Json结构,所以我想那一定是这样的:

{600450:{STATE:STATE1 , CITY:CITY2 , ...} ,  ...}

如果这是真的,那么这种方式可以为您提供帮助:

    public static JSONObject convert(JSONObject first) throws JSONException {
    HashMap<String , HashMap<String , JSONArray>> hashMap = new HashMap<>();
    Iterator<String> keys = first.keys();
    while (keys.hasNext())
    {
        String key = keys.next();
        JSONObject inner = first.getJSONObject(key);
        String state = inner.getString("STATE");
        HashMap<String , JSONArray> stateMap =
                hashMap.computeIfAbsent(state , s -> new HashMap<>());

        String city = inner.getString("CITY");
        JSONArray array = stateMap.computeIfAbsent(city , s->new JSONArray());
        JSONObject o = new JSONObject();
        o.put("ID" , inner.getInt("ID"));
        //in this section you could create int key by calling Integer.parse(String s);
        o.put("CODE" , Integer.valueOf(key));
        o.put("CONTACT" , inner.getInt("CONTACT"));
        array.put(o);

    }

    JSONObject newStructureObject = new JSONObject();
    for(String stateKey:hashMap.keySet())
    {
        JSONArray array = new JSONArray();
        JSONObject cityObject = new JSONObject();
        HashMap<String , JSONArray> cityMap = hashMap.get(stateKey);
        for(String cityKey : cityMap.keySet())
        {
            cityObject.put(cityKey , cityMap.get(cityKey));

        }
        array.put(cityObject);
        newStructureObject.put(stateKey , array);
    }

    return newStructureObject;
}

答案 2 :(得分:0)

假设转换后的初始JSON如下所示:

{
    "600450": {
        "STATE": "STATE1",
        "CITY": "CITY1",
        "ID": 1,
        "CONTACT": 1234
    },
    "600451": {
        "STATE": "STATE2",
        "CITY": "CITY2",
        "ID": 3,
        "CONTACT": 2234
    },
    "600453": {
        "STATE": "STATE1",
        "CITY": "CITY1",
        "ID": 2,
        "CONTACT": 3456
    }
}

这是一个静态方法,可以完全转换为所需的格式:

static JSONObject convert(JSONObject initial) {
        // STATE -> CITY -> Address[]
        Map<String, Map<String, List<Map<String, Object>>>> stateToCityToAddresses = new HashMap<>();

        // Get list of codes
        String[] codes = JSONObject.getNames(initial);

        // Loop over codes - "600450", "600451", "600453", ...
        for (String code : codes) {

            // Get the JSONObject containing state data
            JSONObject state = initial.getJSONObject(code);

            // Extract information from state JSONObject
            String stateName = state.getString("STATE");
            String cityName = state.getString("CITY");
            long id = state.getLong("ID");
            long contact = state.getLong("CONTACT");

            // Some Java 8 awesomeness!
            List<Map<String, Object>> addresses = stateToCityToAddresses
                .computeIfAbsent(stateName, sn -> new HashMap<>()) // This makes sure that there is a Map available to hold cities for a given state
                .computeIfAbsent(cityName, cn -> new ArrayList<>()); // This makes sure that there is a List available to hold addresses for a given city

            // Save data in a map representing a json object like: {"CONTACT":1234,"CODE":600450,"ID":1}
            Map<String, Object> address = new HashMap<>();
            address.put("ID", id);
            address.put("CONTACT", contact);
            address.put("CODE", Long.parseLong(code));

            // Add the address under city
            addresses.add(address);
        }

        // Just use the JSONObject.JSONObject(Map<?, ?>) constructor to get the final result
        JSONObject result = new JSONObject(stateToCityToAddresses);

        // You can sysout the result to see the data
        // System.out.println(result);

        return result;
    }