将对象数组序列化为JSON

8

我有一个类型,它是字典的包装器 - 基本上是一个键/值存储。我想将这种类型的对象数组序列化为JSON。我对JSON和Json.NET(newtonsoft.json)还不太熟悉。

我的类型有一个名为 - ToJson 的方法,它将其字典序列化为以下json格式:

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

然后我试图序列化这些对象的数组

var json = JsonConvert.SerializeObject(objectArray)

当然,这样做不起作用,因为数组中的每个对象都被序列化了,我不知道如何将序列化过程指向我的"ToJson"方法。如果我传递一个字典对象的数组,那么它可以完全按照我的预期工作。
也许我错过了一些序列化属性?
编辑:
阅读了一些文档后,我尝试了一种更简便的方法(在考虑JsonConverter方法之前) - 使用“JsonPropertyAttribute”。将其应用于私有字典成员几乎完成了工作,除了我还要序列化成员名称,这是我不想要的。是否有一种方式可以只使用JsonPropertyAttribute来序列化成员值而不是成员名称?

2
在调用 ToJson() 之前,对数组调用 JsonConvert.SerializeObject 方法。最终结果将是相同的。 - Liam
2
https://dev59.com/OmQm5IYBdhLWcg3wwxLF - Tewr
@alwayslearning 对于你的后续问题,我的回答是:没有办法使用[JsonProperty]属性来消除属性名称。这就是为什么你需要转换器的原因。 - Brian Rogers
2个回答

7
为了使您的包装类被序列化后,其内部字典能够以JSON形式显示,您需要一个自定义的JsonConverterJsonConverter可以直接控制特定类的序列化和/或反序列化过程。
下面是一个适用于您情况的转换器。由于您没有提供有关包装类的详细信息,除了它有一个名为values的字段来保存字典外,我使用了反射来访问它。如果您的类具有直接操作字典的公共方法,则可以更改转换器以使用这些方法。以下是代码:
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;
    }
}

为了将自定义转换器绑定到您的包装类,您可以在类定义中添加一个[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();
    }
}

以下是完整演示,展示了转换器的使用情况。首先对包装类的单个实例进行序列化和反序列化,然后对包装类列表进行序列化和反序列化:

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

输出:

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

-2

尝试将此代码应用于您拥有的任何类型的对象。这是我使用的通用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
}

这并没有解决问题所提出的问题。 - Brian Rogers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接