2015-10-08 121 views
2

我讀一個簡單的JSON ....如何在Groovy的JsonSlurper中維護JSON的順序?

{"A":0,"B":0,"C":2,"D":0,"F":5} 

到Groovy中使用JsonSlurper地圖...

Map gradeDistributon = jsonSlurper.parseText(jsonString) 

但在這個地圖與閉合時,迭代..

gradeDistributon.each{ entry -> 
    println "From map got key ${entry.key}" 

我看到的按鍵不是按原來的JSON順序排列的,例如'C'先出現。我認爲這是因爲Map沒有在Java中維護插入順序。有沒有一種方法可以保持原始JSON的順序?

如果這意味着以不同的方式閱讀JSON(而不是使用JsonSlurper的Map),那麼如果你能告訴我怎麼做,那我就很好。

+4

JSON定義爲無序集合。爲什麼你需要訂單? – Opal

+0

@Opal,我在前端的報告中打印出來,他們希望首先看到等級「A」的計數。 – AbuMariam

+3

所以只需按年級排序。 – Opal

回答

0

我無法與常規2.4.5重現你的行爲,但你可以嘗試使用LinkedHashMap的(允許遍歷映射鍵保持在其中插入的條目順序):

import groovy.json.* 

def jsonText = ''' 
{"A":0,"B":0,"C":2,"D":0,"F":5,"G":7,"H":9} 
''' 

LinkedHashMap json = new JsonSlurper().parseText(jsonText) 
json.each{ entry -> 
    println "${entry.key}" 
} 

注意 :正如@XenoN所述,JsonSlurper()在解析過程中對json鍵進行排序,因此獨立於輸入順序(即{"H":0,"B":0,"A":2,"D":0,"G":5,"F":7,"C":9}),JsonSlurper的輸出始終爲:{"A":2,"B":0,"C":9,"D":0,"F":7,"G":5,"H":0}

使用LinkedHashMap而不是HashMap,我們保留了JsonSlurper給出的順序。

+1

您無法複製它。因爲JsonSlurper通過asc命令它。看看你的例子a b c? – XenoN

+0

@XenoN:你說得對,我用過的輸入例子掩蓋了JsonSlurper排序行爲,但是提出這個問題的人有相反的問題:json在最後沒有按字母順序排序。使用LinkedHashMap,我們可以保證保持JsonSlurper –

+0

給出的排序順序。但他以虛擬數據爲例,他的真實代碼是不同的,我敢打賭。他認爲地圖搞亂了他的命令。其實Slurper是。這就是爲什麼你不能再現它 – XenoN

0

所以它只是一個排序鍵JsonSlurper內置地圖後,對於我剛剛讀到這種種默認密鑰的樹形圖事..

TreeMap gradeDistributon = jsonSlurper.parseText(jsonString) 
+0

出於好奇,我無法重現你的行爲,甚至沒有洗牌JSON(默認情況下,看起來像JsonSlurper排序元素)。你用什麼版本的groovy? –

1

您可以設置JVM系統屬性jdk.map.althashing.threshold使JsonSlurper使用LinkedHashMap而不是TreeMap作爲內部Map實現,例如-Djdk.map.althashing.threshold=512

原因是source codegroovy.json.internal.LazyMap使用JsonSlurper

private static final String JDK_MAP_ALTHASHING_SYSPROP = System.getProperty("jdk.map.althashing.threshold"); 

private void buildIfNeeded() { 
    if (map == null) { 
     /** added to avoid hash collision attack. */ 
     if (Sys.is1_7OrLater() && JDK_MAP_ALTHASHING_SYSPROP != null) { 
      map = new LinkedHashMap<String, Object>(size, 0.01f); 
     } else { 
      map = new TreeMap<String, Object>(); 
     } 
    } 
} 

請注意,該解決方案應該用作黑客,因爲它取決於Groovy的內部實現細節。所以這個行爲在未來的Groovy版本中可能會改變。

有關詳細信息,請參閱我的blog post