2014-06-25 178 views
4

我有一個JSON字符串,我從包含重複鍵的數據庫中獲取。我想通過將它們的值組合到一個數組中來移除重複的鍵。將具有重複鍵的JSON對象轉換爲JSON數組

例如

輸入

{ 
"a":"b", 
"c":"d", 
"c":"e", 
"f":"g" 
} 

輸出

{ 
"a":"b", 
"c":["d","e"], 
"f":"g" 
} 

的實際數據是可以被嵌套在較大的文件。我不會提前知道什麼或有多少對。

我需要爲此使用Java。 org.json拋出一個異常,因爲重複鍵,gson可以解析字符串,但每個重複的鍵都會覆蓋最後一個鍵。我需要保留所有的數據。

如果可能的話,我想做到這一點,而無需編輯任何庫代碼

+1

JSON對象不能包含具有相同鍵的2個項目。在你的例子json中,c的第一個外觀將被覆蓋。你可以通過http://jsonlint.com/ –

+0

驗證你的json來看到這一點。從技術上講,你從數據庫獲得的東西不是「JSON」。您需要重新評估數據的寫入方式,或者更可能需要自己爲數據編寫某種解析器。我想不出一個期望通過這種方式來轉換數據的庫。 – Tejs

+0

根據這個問題,它是有效的,儘管解析器不允許出於顯而易見的原因。我真的不在乎,如果它不是有效的JSON,只要我可以將重複值的字符串格式轉換爲字符串格式沒有重複值http://stackoverflow.com/questions/21832701/does-json-syntax-allow-duplicate-鍵入對象 – adamF

回答

1

作爲當今org.json庫版本20170516提供accumulate()方法存儲重複鍵條目爲JSONArray

JSONObject jsonObject = new JSONObject(); 
jsonObject.accumulate("a", "b"); 
jsonObject.accumulate("c", "d"); 
jsonObject.accumulate("c", "e"); 
jsonObject.accumulate("f", "g"); 
System.out.println(jsonObject); 

輸出:
{
「一」: 「B」,
「c」:[「d」,「e」],
「f」:「g」
}

+0

真棒!不再需要它,但只是我很久以前想要的:) – adamF

+0

認爲是這樣,因爲問題是3歲,但嘿它可以對別人有用:) – Kainix

0

爲了完成你想要什麼,你需要創建某種自定義類的,因爲JSON不能在技術上有在一個關鍵的2個值。下面是一個例子:

public class SomeClass { 

Map<String, List<Object>> values = new HashMap<String, List<Object>>(); 

public void add(String key, Object o) { 
    List<Object> value = new ArrayList<Object>(); 
    if (values.containsKey(key)) { 
     value = values.get(key); 
    } 
    value.add(o); 
    values.put(key, value); 
} 

public JSONObject toJson() throws JSONException { 
    JSONObject json = new JSONObject(); 
    JSONArray tempArray = null; 

    for (Entry<String, List<Object>> en : values.entrySet()) { 
     tempArray = new JSONArray(); 
     for (Object o : en.getValue()) { 
      tempArray.add(o); 
     } 
     json.put(en.getKey(), tempArray); 
    } 

    return json; 
} 
} 

然後,您可以從數據庫中檢索值,從數據庫中調用.add(String key, Object o)功能與列名和值(爲Object PARAM)。完成後請致電.toJson()

+0

這太難編碼了。我給出的例子只是爲了說明問題。我的實際數據是一個很大的嵌套文件,我不知道提前瞭解什麼或有多少字段。即使我將它抽象出來,我仍然需要一種可靠地解析json字符串的方法。 – adamF

+0

使其具有通用性。在JSON中可以有任何類型的值。 – Braj

+0

使用地圖進行通用化。每次讀入一個鍵值對,檢查鍵是否存在於映射中,如果存在,則將該值添加到該鍵的列表中,如果沒有,則創建一個包含該值的新列表並添加它在那個關鍵。然後,在toJSON中,遍歷每個'Entry' –

2

我想通過將它們的值組合到一個數組中去除重複鍵。

除了JSON解析庫之外,還有其他想法。這是一個非常簡單的Java程序,它使用String.split()方法將Json字符串轉換爲Map<String, List<String>>,而不使用任何庫

示例代碼:

String jsonString = ... 
// remove enclosing braces and double quotes 
jsonString = jsonString.substring(2, jsonString.length() - 2); 

Map<String, List<String>> map = new HashMap<String, List<String>>(); 
for (String values : jsonString.split("\",\"")) { 
    String[] keyValue = values.split("\":\""); 
    String key = keyValue[0]; 
    String value = keyValue[1]; 

    if (!map.containsKey(key)) { 
     map.put(key, new ArrayList<String>()); 
    } 
    map.get(key).add(value); 
} 

輸出:

{ 
    "f": ["g"], 
    "c": ["d","e"], 
    "a": ["b"] 
} 
0

感謝Mike Elofson和Braj幫助我在正確的方向。我只想讓具有多個值的鍵變成數組,所以我不得不修改一些代碼。最終我希望它能夠嵌套JSON,因爲它目前假設它是平坦的。但是,以下代碼適用於目前我需要的內容。

public static String repeatedKeysToArrays(String jsonIn) throws JSONException 
{ 
    //This assumes that the json is flat 
    String jsonString = jsonIn.substring(2, jsonIn.length() - 2); 

    JSONObject obj = new JSONObject(); 
    for (String values : jsonString.split("\",\"")) { 
     String[] keyValue = values.split("\":\""); 
     String key = keyValue[0]; 
     String value = ""; 
     if (keyValue.length>1) value = keyValue[1]; 

     if (!obj.has(key)) { 
      obj.put(key, value); 
     } else { 
      Object Oold = obj.get(key); 
      ArrayList<String> newlist = new ArrayList<String>(); 

      //Try to cast as JSONArray. Otherwise, assume it is a String 
      if (Oold.getClass().equals(JSONArray.class)) { 
       JSONArray old = (JSONArray)Oold; 
       //Build replacement value 
       for (int i=0; i<old.length(); i++) { 
        newlist.add(old.getString(i)); 
       } 
      } 
      else if (Oold.getClass().equals(String.class)) newlist = new ArrayList<String>(Arrays.asList(new String[] {(String)Oold})); 
      newlist.add(value); 

      JSONArray newarr = new JSONArray(newlist); 
      obj.put(key,newarr);     
     } 
    } 
    return obj.toString(); 
}