【问题标题】:JSON serialization using newtonsoft in C#在 C# 中使用 newtonsoft 进行 JSON 序列化
【发布时间】:2015-06-03 11:04:56
【问题描述】:

我有以下模型结构。

 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"
      }
   ]
}

【问题讨论】:

    标签: c# json serialization json.net jsonserializer


    【解决方案1】:

    如果您使用 Json.NET 5.0 release 5 或更高版本,则不需要嵌套泛型集合。 您可以使用JsonExtensionDataAttribute,以便Item 字典的键和值将被序列化为父对象的一部分。

    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));
    

    注意你需要Dictionary&lt;string, object&gt;而不是Dictionary&lt;string, string&gt;

    这是我得到的结果:

    {
      "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

    【讨论】:

      【解决方案2】:

      如果你这样改变,结果会是你所期望的;

      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"
          }
        ]
      }
      

      【讨论】:

      • 有了这个我可以实现,但是 Visual Studio 代码分析会显示一个错误,不使用嵌套的通用列表。 CA1006:不要在成员签名中嵌套泛型类型——
      • 这只是一个警告,随它去吧。很好
      • 我不能。这不应该被压制。这些是我们在项目中的指导方针。
      • 这只是微软设计的警告。意思是您的设计很复杂,但如果这是您想要的输出,那么您就无能为力了。 msdn.microsoft.com/en-us/library/ms182144.aspx
      【解决方案3】:

      如果您无法更改 C#,则可以使用 View 模型并使用适当的结构。它可能比更改 JSON 设置更简单,更容易返回和更明确:

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

      应根据需要进行序列化。

      【讨论】:

      • 有了这个我可以实现,但是 Visual Studio 代码分析会显示一个错误,不使用嵌套的通用列表。 CA1006:不要在成员签名中嵌套泛型类型
      • 这只是微软设计的警告。意思是您的设计很复杂,但如果这是您想要的输出,那么您无能为力。 msdn.microsoft.com/en-us/library/ms182144.aspx
      【解决方案4】:

      您可以按如下方式实现自定义行为:

      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 });
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-26
        • 1970-01-01
        相关资源
        最近更新 更多