简体   繁体   English

将对象数组序列化为JSON

[英]Serializing an object array to JSON

I have a type which is a wrapper over a dictionary - basically a key/value store. 我的类型是字典的包装器-基本上是键/值存储。 I would like to serialize an array of objects of this type to JSON. 我想将此类型的对象数组序列化为JSON。 I am pretty new to JSON and Json.NET (newtonsoft.json). 我对JSON和Json.NET(newtonsoft.json)很陌生。

My type has a method called - ToJson which serializes its dictionary to json as follows 我的类型有一个称为ToJson的方法,该方法将其字典序列化为json,如下所示

public string ToJson()
{
  return JsonConvert.SerializeObject(this.values);
}    

And then I try to serialize an array of these objects 然后我尝试序列化这些对象的数组

var json = JsonConvert.SerializeObject(objectArray)

Of course this does not work because each object in the array is serialized and I do not know how to direct the serialization process to my 'ToJson' method for each object. 当然,这是行不通的,因为数组中的每个对象都已序列化,而且我不知道如何将序列化过程定向到每个对象的“ ToJson”方法。

I can get it to work exactly as I want it if I pass in an array of Dictionary objects. 如果传入一个Dictionary对象数组,则可以使其完全按照我的要求工作。

Maybe I am missing some serialization attribute? 也许我缺少一些序列化属性?

EDIT: 编辑:

After reading some more documentation I tried a shorter way (before considering the JsonConverter approach) - using the 'JsonPropertyAttribute'. 阅读更多文档后,我尝试了一种更短的方法(在考虑JsonConverter方法之前)-使用'JsonPropertyAttribute'。 Applying it to the private Dictionary member almost did the job except that I also get the member name serialized, which I do not want. 将它应用于私有Dictionary成员几乎可以完成这项工作,除了我还可以序列化成员名,这是我不想要的。 Any way to just serialize the member value and not the member name by using the JsonPropertyAttribute? 有什么方法可以使用JsonPropertyAttribute序列化成员值而不是序列名?

In order to serialize your wrapper class such that its internal dictionary appears in the JSON as if the wrapper were not there, you need a custom JsonConverter . 为了序列化您的包装器类,以便其内部字典像不存在包装器一样出现在JSON中,您需要一个自定义JsonConverter A JsonConverter gives you direct control over what gets serialized and/or deserialized for a particular class. JsonConverter使您可以直接控制对特定类进行序列化和/或反序列化的内容。

Below is a converter that should work for your case. 以下是适用于您的情况的转换器。 Since you didn't really provide any details about your wrapper class other than it has a field called values to hold the dictionary, I used reflection to gain access to it. 由于除了包装类之外,您实际上没有提供任何详细信息,因为包装类有一个名为values的字段来保存字典,所以我使用了反射来访问它。 If your class has public methods to manipulate the dictionary directly, you can change the converter to use those methods instead, if you prefer. 如果您的类具有可直接操作字典的公共方法,则可以根据需要将转换器更改为使用这些方法。 Here is the code: 这是代码:

class DictionaryWrapperConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(MyWrapper));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        MyWrapper wrapper = (MyWrapper)value;
        FieldInfo field = typeof(MyWrapper).GetField("values", BindingFlags.NonPublic | BindingFlags.Instance);
        JObject jo = JObject.FromObject(field.GetValue(wrapper));
        jo.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        MyWrapper wrapper = new MyWrapper();
        FieldInfo field = typeof(MyWrapper).GetField("values", BindingFlags.NonPublic | BindingFlags.Instance);
        field.SetValue(wrapper, jo.ToObject(field.FieldType));
        return wrapper;
    }
}

To tie the custom converter to your wrapper class, you can add a [JsonConverter] attribute to the class definition: 要将自定义转换器绑定到包装器类,可以在类定义中添加[JsonConverter]属性:

[JsonConverter(typeof(DictionaryWrapperConverter))]
class MyWrapper : IEnumerable
{
    Dictionary<string, string> values = new Dictionary<string, string>();

    public void Add(string key, string value)
    {
        values.Add(key, value);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return values.GetEnumerator();
    }
}

Here is a full demo showing the converter in action, first serializing and deserializing a single instance of the wrapper class, then serializing and deserializing a list of wrappers: 这是一个完整的演示,展示了运行中的转换器,首先序列化和反序列化包装类的单个实例,然后序列化和反序列化包装器列表:

class Program
{
    static void Main(string[] args)
    {
        MyWrapper wrapper = new MyWrapper();
        wrapper.Add("foo", "bar");
        wrapper.Add("fizz", "bang");

        // serialize single wrapper instance
        string json = JsonConvert.SerializeObject(wrapper, Formatting.Indented);

        Console.WriteLine(json);
        Console.WriteLine();

        // deserialize single wrapper instance
        wrapper = JsonConvert.DeserializeObject<MyWrapper>(json);

        foreach (KeyValuePair<string, string> kvp in wrapper)
        {
            Console.WriteLine(kvp.Key + "=" + kvp.Value);
        }
        Console.WriteLine();
        Console.WriteLine("----------\n");

        MyWrapper wrapper2 = new MyWrapper();
        wrapper2.Add("a", "1");
        wrapper2.Add("b", "2");
        wrapper2.Add("c", "3");

        List<MyWrapper> list = new List<MyWrapper> { wrapper, wrapper2 };

        // serialize list of wrappers
        json = JsonConvert.SerializeObject(list, Formatting.Indented);

        Console.WriteLine(json);
        Console.WriteLine();

        // deserialize list of wrappers
        list = JsonConvert.DeserializeObject<List<MyWrapper>>(json);

        foreach (MyWrapper w in list)
        {
            foreach (KeyValuePair<string, string> kvp in w)
            {
                Console.WriteLine(kvp.Key + "=" + kvp.Value);
            }
            Console.WriteLine();
        }
    }
}

Output: 输出:

{
  "foo": "bar",
  "fizz": "bang"
}

foo=bar
fizz=bang

----------

[
  {
    "foo": "bar",
    "fizz": "bang"
  },
  {
    "a": "1",
    "b": "2",
    "c": "3"
  }
]

foo=bar
fizz=bang

a=1
b=2
c=3

Try this to any type of object you have. 对您拥有的任何类型的对象尝试此操作。 It's a generic JSON Serializer code I use 这是我使用的通用JSON序列化器代码

public class JsonUtils
{
    #region
    public static string JsonSerializer<T>(T t)
    {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
        MemoryStream ms = new MemoryStream();
        ser.WriteObject(ms, t);
        string jsonString = Encoding.UTF8.GetString(ms.ToArray());
        ms.Close();
        return jsonString;
    }
    /// <summary>
    /// JSON Deserialization
    /// </summary>
    public static T JsonDeserialize<T>(string jsonString)
    {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
        MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
        T obj = (T)ser.ReadObject(ms);
        return obj;
    }
    #endregion
}

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

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