2015-06-03 26 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 }); 
    } 
} 
相关问题