我有一个类型,它是字典上的包装器 - 基本上是一个键/值存储。我想将这种类型的对象数组序列化为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'。将它应用于私有字典成员几乎完成了这项工作,除了我还得到序列化的成员名称,这是我不想要的。有什么方法可以通过使用JsonPropertyAttribute来序列化成员值而不是成员名吗?
答案 0 :(得分:7)
为了序列化您的包装类,使其内部字典出现在JSON中,就像包装器不在那里一样,您需要一个自定义JsonConverter
。 JsonConverter
使您可以直接控制对特定类进行序列化和/或反序列化的内容。
以下是适用于您的情况的转换器。由于你没有真正提供有关你的包装类的任何细节,除了它有一个名为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
答案 1 :(得分:-1)
尝试使用任何类型的对象。它是我使用的通用JSON Serializer代码
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
}