繁体   English   中英

在C#中使用newtonsoft进行JSON序列化

[英]JSON serialization using newtonsoft in C#

我有以下模型结构。

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

如果使用Json.NET 5.0版本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<string, object>而不是Dictionary<string, string>

这是我得到的结果:

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

如果您像这样进行更改,结果将是您期望的;

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

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

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

应该按需要序列化。

您可以实现自定义行为,如下所示:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM