【问题标题】:Serializing an object array to JSON将对象数组序列化为 JSON
【发布时间】:2014-03-05 00:45:56
【问题描述】:

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

我的类型有一个名为 - ToJson 的方法,它将其字典序列化为 json,如下所示

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

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

var json = JsonConvert.SerializeObject(objectArray)

当然这不起作用,因为数组中的每个对象都是序列化的,我不知道如何将序列化过程引导到每个对象的“ToJson”方法。

如果我传入一个 Dictionary 对象数组,我可以让它完全按照我想要的方式工作。

也许我缺少一些序列化属性?

编辑:

在阅读了更多文档后,我尝试了一种更短的方法(在考虑 JsonConverter 方法之前) - 使用“JsonPropertyAttribute”。将它应用于私有 Dictionary 成员几乎完成了这项工作,只是我还序列化了成员名称,这是我不想要的。有什么方法可以使用 JsonPropertyAttribute 仅序列化成员值而不是成员名称?

【问题讨论】:

  • 在阵列上调用JsonConvert.SerializeObject先于调用ToJson()。净结果将是相同的。
  • @alwayslearning 回答您的后续问题:不,没有办法使用[JsonProperty] 属性消除属性名称。这就是您需要转换器的原因。

标签: c# .net json json.net


【解决方案1】:

为了序列化您的包装器类,使其内部字典出现在 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
    }
    

    【讨论】:

    • 这并不能解决问题中提出的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    相关资源
    最近更新 更多