2010-07-25 197 views
78

有沒有一種方法可以使用JSON.NET來指定序列化JSON對象中字段的順序?使用JSON.NET的序列化字段的順序

指定單個字段總是首先出現就足夠了。

+0

只是出於好奇,爲什麼你會在意嗎? – 2012-07-03 10:41:44

+3

我想他可能會首先顯示ID字段(或類似字段),然後是所有其他字段。對於最終用戶而言,這比對以A..I – michaelAngelo 2012-11-14 14:53:54

+1

開頭的字段之後的字符進行查找更友好.JSON屬性被定義爲無序。我認爲在序列化過程中強制執行某個OUTPUT命令是絕對沒問題的(也許是爲了目擊JSON),但是在反序列化的任何特定順序上創建DEPENDENCY將是一個錯誤的決定。 – DaBlick 2015-06-30 12:58:28

回答

-1

我隨後經由反射JsonConvert.SerializeObject(key)方法調用(其中鍵是一個IList),發現JsonSerializerInternalWriter.SerializeList被調用。它需要一個列表,並通過

for (int i = 0; i < values.Count; i++) { ...

其中值是IList的參數帶來的遍歷。

簡短的回答是......不,沒有內置的方法來設置字段的順序列在JSON字符串中。

+9

簡短的回答,但可能過時。看看史蒂夫的回答(由詹姆斯牛頓王支持) – 2015-08-01 13:41:20

-3

JSON格式的字段沒有順序,所以定義一個順序是沒有意義的。

{ id: 1, name: 'John' }相當於{ name: 'John', id: 1 }(兩者都表示嚴格相等對象實例)

+0

這隻適用於「在線」傳輸,而不適用於另一端的消耗。一旦反序列化,基本上我並不期望命令持續存在。 – 2010-07-25 21:03:45

+0

你在說什麼? JSON是一種允許對象序列化/反序列化的格式。在OOP的對象字段中沒有概念*順序*。 – 2010-07-25 21:04:50

+9

@Darin - 但是在序列化中有一個命令。 「{id:1,name:'John'}」and「{name:'John',id:1}」與* strings *不同,這就是我所關心的。當然,反序列化時對象是等價的。 – 2010-07-25 21:09:21

88

您可以通過執行IContractResolver或覆蓋DefaultContractResolverCreateProperties方法實際控制訂單。

這裏是我的簡單實現IContractResolver的例子字母定購屬性:

public class OrderedContractResolver : DefaultContractResolver 
{ 
    protected override System.Collections.Generic.IList<JsonProperty> CreateProperties(System.Type type, MemberSerialization memberSerialization) 
    { 
     return base.CreateProperties(type, memberSerialization).OrderBy(p => p.PropertyName).ToList(); 
    } 
} 

,然後設置設置和序列化對象,而JSON字段將是按字母順序排列:

var settings = new JsonSerializerSettings() 
{ 
    ContractResolver = new OrderedContractResolver() 
}; 

var json = JsonConvert.SerializeObject(obj, Formatting.Indented, settings); 
+1

完美地爲我工作 – michaelAngelo 2012-11-14 14:54:26

+0

謝謝!我正在找那個! – esskar 2013-03-16 18:15:42

+3

這非常有用(+1),但有一點需要注意:它出現的字典序列化不會使用此CreateProperties自定義。他們序列化好,但不會最終排序。我假設有一種不同的方式來定製字典的序列化,但我還沒有找到它。 – solublefish 2015-03-06 19:46:12

0

以下遞歸方法使用反射來對現有的JObject實例上的內部令牌列表進行排序,而不是創建一個br和新的排序對象圖。此代碼依賴於內部的Json.NET實現細節,不應在生產中使用。

void SortProperties(JToken token) 
{ 
    var obj = token as JObject; 
    if (obj != null) 
    { 
     var props = typeof (JObject) 
      .GetField("_properties", 
         BindingFlags.NonPublic | BindingFlags.Instance) 
      .GetValue(obj); 
     var items = typeof (Collection<JToken>) 
      .GetField("items", BindingFlags.NonPublic | BindingFlags.Instance) 
      .GetValue(props); 
     ArrayList.Adapter((IList) items) 
      .Sort(new ComparisonComparer(
       (x, y) => 
       { 
        var xProp = x as JProperty; 
        var yProp = y as JProperty; 
        return xProp != null && yProp != null 
         ? string.Compare(xProp.Name, yProp.Name) 
         : 0; 
       })); 
    } 
    foreach (var child in token.Children()) 
    { 
     SortProperties(child); 
    } 
} 
168

支持的方法是使用上要設置訂單的類屬性的屬性JsonPropertyRead the JsonPropertyAttribute order documentation for more information

通過JsonPropertyOrder值,序列化程序將處理其餘的。

[JsonProperty(Order = 1)] 

這是非常相似的

DataMember(Order = 1) 
System.Runtime.Serialization

+61

使用'JsonPropertyAttribute'的'Order'屬性可以控制字段序列化/反序列化的順序。但是,如果您在所有其他屬性上設置的訂單大於1,則僅將訂單設置爲1。默認情況下,沒有訂單設置的任何屬性將被賦予-1的順序。所以你必須給所有序列化的屬性和順序,或者將你的第一項設置爲-2。 – 2014-02-25 11:23:27

+0

這個解決方案對我來說非常合適。^5 – 2015-07-16 21:58:33

+1

它適用於序列化,但是在反序列化中沒有考慮該順序。根據文檔,order屬性用於序列化和反序列化。有沒有解決方法? – cangosta 2015-12-21 18:46:36

10

在我的情況下,Mattias的答案沒有奏效。 CreateProperties方法從未被調用過。

在對Newtonsoft.Json內部進行了一些調試之後,我想出了另一種解決方案。

public class JsonUtility 
{ 
    public static string NormalizeJsonString(string json) 
    { 
     // Parse json string into JObject. 
     var parsedObject = JObject.Parse(json); 

     // Sort properties of JObject. 
     var normalizedObject = SortPropertiesAlphabetically(parsedObject); 

     // Serialize JObject . 
     return JsonConvert.SerializeObject(normalizedObject); 
    } 

    private static JObject SortPropertiesAlphabetically(JObject original) 
    { 
     var result = new JObject(); 

     foreach (var property in original.Properties().ToList().OrderBy(p => p.Name)) 
     { 
      var value = property.Value as JObject; 

      if (value != null) 
      { 
       value = SortPropertiesAlphabetically(value); 
       result.Add(property.Name, value); 
      } 
      else 
      { 
       result.Add(property.Name, property.Value); 
      } 
     } 

     return result; 
    } 
} 
+0

這是使用字典時所需的修復方法。 – noocyte 2015-06-03 08:39:38

0

實際上,因爲我的目標已經是一個JObject,我用以下解決方案:

public class SortedJObject : JObject 
{ 
    public SortedJObject(JObject other) 
    { 
     var pairs = new List<KeyValuePair<string, JToken>>(); 
     foreach (var pair in other) 
     { 
      pairs.Add(pair); 
     } 
     pairs.OrderBy(p => p.Key).ForEach(pair => this[pair.Key] = pair.Value); 
    } 
} 

,然後用它是這樣的:

string serializedObj = JsonConvert.SerializeObject(new SortedJObject(dataObject)); 
7

在我的情況niaher的解決方案做了不工作,因爲它沒有處理數組中的對象。

基於他的解決辦法,這是我想出了

public static class JsonUtility 
{ 
    public static string NormalizeJsonString(string json) 
    { 
     JToken parsed = JToken.Parse(json); 

     JToken normalized = NormalizeToken(parsed); 

     return JsonConvert.SerializeObject(normalized); 
    } 

    private static JToken NormalizeToken(JToken token) 
    { 
     JObject o; 
     JArray array; 
     if ((o = token as JObject) != null) 
     { 
      List<JProperty> orderedProperties = new List<JProperty>(o.Properties()); 
      orderedProperties.Sort(delegate(JProperty x, JProperty y) { return x.Name.CompareTo(y.Name); }); 
      JObject normalized = new JObject(); 
      foreach (JProperty property in orderedProperties) 
      { 
       normalized.Add(property.Name, NormalizeToken(property.Value)); 
      } 
      return normalized; 
     } 
     else if ((array = token as JArray) != null) 
     { 
      for (int i = 0; i < array.Count; i++) 
      { 
       array[i] = NormalizeToken(array[i]); 
      } 
      return array; 
     } 
     else 
     { 
      return token; 
     } 
    } 
} 
0

如果你控制(即寫入)類,把屬性按字母順序排列,他們將按照字母順序序列化時JsonConvert.SerializeObject()被調用。

2

查理指出,可以一定程度上受到的類本身訂貨屬性控制JSON屬性的排序。不幸的是,這種方法不適用於從基類繼承的屬性。基類屬性將按照它們在代碼中的佈局進行排序,但會顯示在基類屬性之前。

而且任何人都知道爲什麼,你可能想按字母順序排列JSON性能,它是一個整體更容易與原始JSON文件的工作,特別是對類有很多的屬性,如果他們是有序的。