2015-06-03 60 views
0

我有以下模型結構。在C中使用newtonsoft的JSON序列化#

public class ReferenceData 
    { 
     public string Version { get; set; } 

     public List<DataItem> Data { get; set; } 
    } 


    public class DataItem 
    { 
     public Dictionary<string, string> Item { get; set; } 
    } 

在詞典我添加的關鍵值對和與KeyValuePairConverter設置串行化。

var settings = new JsonSerializerSettings 
       { 
        ContractResolver = new CamelCasePropertyNamesContractResolver(), 
        NullValueHandling = NullValueHandling.Ignore, 
        Converters = new List<JsonConverter>() { new KeyValuePairConverter() } 
       }; 

var object = Newtonsoft.Json.JsonConvert.SerializeObject(
        referenceData, 
        Formatting.None, 
        settings 
        ); 

和輸出是,

{ 
     "data":[ 
      { 
      "item":{ 
       "ShortDescription":"Lorem ipssumm", 
       "Title":"some text", 
       "PlanType":"ZEROP", 
      } 
      }, 
      { 
      "item":{ 
       "ShortDescription":"Lorem ipssumm", 
       "Title":"some text", 
       "PlanType":"ZEROP", 
      } 
      }, 
      { 
      "item":{ 
       "ShortDescription":"Lorem ipssumm", 
       "Title":"some text", 
       "PlanType":"ZEROP", 
      } 
      } 
     ] 
    } 

如果我們不想item在序列化的字符串來表現,需要什麼樣的設置在JsonSerializerSettings做或有任何其他的方式做那。

請注意,我不能改變模型結構,因爲它是必需的。

輸出應該是:

{ 
    "data":[ 
     { 
     "ShortDescription":"Lorem ipssumm", 
     "Title":"some text", 
     "PlanType":"ZEROP" 
     }, 
     { 
     "ShortDescription":"Lorem ipssumm", 
     "Title":"some text", 
     "PlanType":"ZEROP" 
     }, 
     { 
     "ShortDescription":"Lorem ipssumm", 
     "Title":"some text", 
     "PlanType":"ZEROP" 
     } 
    ] 
} 

回答

4

如果您使用Json.NET 5.0版本5或更高版本,則不需要嵌套泛型集合。 您可以使用JsonExtensionDataAttribute,這樣Item字典的鍵和值將被序列化爲父對象的一部分。你需要Dictionary<string, object>而不是Dictionary<string, string>

public class ReferenceData 
{ 
    public string version { get; set; } 
    public List<DataItem> data { get; set; } 
} 

public class DataItem 
{ 
    [JsonExtensionData] 
    public IDictionary<string, object> item { get; set; } 
} 

// ... 

var referenceData = new ReferenceData { 
    version = "1.0", 
    data = new List<DataItem> { 
     new DataItem { 
      item = new Dictionary<string, object> { 
       {"1", "2"}, 
       {"3", "4"} 
      } 
     }, 
     new DataItem { 
      item = new Dictionary<string, object> { 
       {"5", "8"}, 
       {"6", "7"} 
      } 
     } 
    } 
}; 

Console.WriteLine(JsonConvert.SerializeObject(referenceData)); 

留意。

下面是結果我得到:

{ 
    "version": "1.0", 
    "data": [ 
    { 
     "1": "2", 
     "3": "4" 
    }, 
    { 
     "5": "8", 
     "6": "7" 
    } 
    ] 
} 

很明顯,你可以刪除Version屬性來獲得預期的結果。

更多在這裏閱讀: http://james.newtonking.com/archive/2013/05/08/json-net-5-0-release-5-defaultsettings-and-extension-data

1

如果改變這樣的結果將是您所期望的;

public class ReferenceData 
{ 
    public string Version { get; set; } 

    public List<Dictionary<string, string>> Data { get; set; } 
} 

可能的其他解決方案是;

ReferenceData r = new ReferenceData(); 

r.Data = new List<DataItem>(); 

r.Data.Add(new DataItem { Item = new Dictionary<string, string>() { { "1", "2" }, { "3", "4" } } }); 



var anon = new 
{ 
    data = r.Data.ToList().Select(x => 
     { 
      dynamic data = new ExpandoObject(); 

      IDictionary<string, object> dictionary = (IDictionary<string, object>)data; 

      foreach (var key in x.Item.Keys) 
       dictionary.Add(key, x.Item[key]); 

      return dictionary; 
     } 
    ) 
}; 

var result = JsonConvert.SerializeObject(anon); 

結果:

{ 
    "data": [ 
    { 
     "1": "2", 
     "3": "4" 
    } 
    ] 
} 
+0

有了這個,我可以實現的,但Visual Studio代碼分析會顯示一個錯誤,不使用使用嵌套的通用列表。 CA1006:不要在會員簽名中嵌套泛型類型 - – PaRsH

+0

只是一個警告,隨它去吧。它的罰款 – Mert

+0

我不能。這不應該被壓制。這些是我們在項目中的指導原則。 – PaRsH

0

如果你不能改變C#可以使用你視圖模型,並用適當的結構。這可能不是改變JSON設置更簡單,更容易恢復和更明確的:根據您的需要

public class ReferenceData 
{ 
    public string Version { get; set; } 
    public List<Dictionary<string, string>> Data { get; set; } 
} 

應該連載。

+0

有了這個我可以實現,但Visual Studio代碼分析將顯示一個錯誤,不使用使用嵌套通用列表。 CA1006:不要在成員簽名中嵌套泛型類型 – PaRsH

+0

這只是Microsoft設計警告。這就是說你的設計很複雜,但如果這是你想要的產出,那麼你可以做的事情就不多了。 msdn.microsoft.com/en-us/library/ms182144.aspx – Stu

0

如下您可以實現自定義的行爲:

class Program { 
    static void Main(string[] args) { 
     var referenceData = new ReferenceData() { 
      Data = new List<DataItem>() { 
       new DataItem(){ 
        Item = new Dictionary<string,string>() { 
         {"ShortDescription", "Lorem ipssumm"}, 
         {"Title", "some text"}, 
         {"PlanType", "ZEROP"}, 
        } 
       }, 
       new DataItem(){ 
        Item = new Dictionary<string,string>() { 
         {"ShortDescription", "Lorem ipssumm"}, 
         {"Title", "some text"}, 
         {"PlanType", "ZEROP"}, 
        } 
       }, 
       new DataItem(){ 
        Item = new Dictionary<string,string>() { 
         {"ShortDescription", "Lorem ipssumm"}, 
         {"Title", "some text"}, 
         {"PlanType", "ZEROP"}, 
        } 
       } 
      } 
     }; 

     var settings = new JsonSerializerSettings { 
      ContractResolver = new CamelCasePropertyNamesContractResolver(), 
      NullValueHandling = NullValueHandling.Ignore, 
      Converters = new List<JsonConverter>() { new KeyValuePairConverter(), new CustomJsonSerializableConverter() } 
     }; 

     File.WriteAllText("hello.json", Newtonsoft.Json.JsonConvert.SerializeObject(
      referenceData, 
      Formatting.Indented, 
      settings 
     )); 
    } 
} 

public class ReferenceData { 
    public string Version { get; set; } 
    public List<DataItem> Data { get; set; } 
} 


[CustomJsonSerializable] 
public class DataItem { 
    public Dictionary<string, string> Item { get; set; } 

    public static void WriteJson(JsonWriter writer, DataItem value, JsonSerializer serializer) { 
     serializer.Serialize(writer, value.Item); 
    } 

    public static DataItem ReadJson(JsonReader reader, DataItem existingValue, JsonSerializer serializer) { 
     DataItem result = new DataItem(); 
     result.Item = serializer.Deserialize<Dictionary<string, string>>(reader); 
     return result; 
    } 
} 

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] 
public class CustomJsonSerializableAttribute : Attribute { 
    public readonly string Read; 
    public readonly string Write; 

    public CustomJsonSerializableAttribute() 
     : this(null, null) { 
    } 

    public CustomJsonSerializableAttribute(string read, string write) { 
     this.Read = read; 
     this.Write = write; 
    } 
} 

public class CustomJsonSerializableConverter : JsonConverter { 
    public override bool CanConvert(Type objectType) { 
     return objectType.GetCustomAttribute(typeof(CustomJsonSerializableAttribute), false) != null; 
    } 

    public override bool CanWrite { 
     get { 
      return true; 
     } 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { 
     if(value != null) { 
      var t = value.GetType(); 
      var attr = (CustomJsonSerializableAttribute)t.GetCustomAttribute(typeof(CustomJsonSerializableAttribute), false); 
      var @delegate = t.GetMethod(attr.Write ?? "WriteJson", new Type[] { typeof(JsonWriter), t, typeof(JsonSerializer) }); 
      @delegate.Invoke(null, new object[] { writer, value, serializer }); 
     } else { 
      serializer.Serialize(writer, null); 
     } 
    } 

    public override bool CanRead { 
     get { 
      return true; 
     } 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { 
     var t = existingValue.GetType(); 
     var attr = (CustomJsonSerializableAttribute)t.GetCustomAttribute(typeof(CustomJsonSerializableAttribute), false); 
     var @delegate = t.GetMethod(attr.Read ?? "ReadJson", new Type[] { typeof(JsonReader), t, typeof(JsonSerializer) }); 
     return @delegate.Invoke(null, new object[] { reader, existingValue, serializer }); 
    } 
} 
相關問題