我有一些看起来像这样的json:
[
{
"MenuItem1": [
{ "SubItem1": [ ] },
{ "SubItem2": [ ] },
{ "SubItem3": [
{ "SubSubItem": [ ] }
]
}
]
},
{ "MenuItem2": [ ] }
]
这可以用以下C#数据结构表示:
class MenuItem
{
Dictionary<string, MenuItem[]> Items;
}
我尝试将其反序列化为
MenuItem[] roots = JsonConvert.DeserializeObject<MenuItem[]>(json);
但它不起作用,因为它不知道Items
成员是这个字典数据应该在递归调用上的位置。我怎样才能做到这一点?
答案 0 :(得分:2)
您的基本问题是您的JSON不代表MenuItem
类列表的字典。相反,它代表MenuItem
类的字典列表 - 与数据模型中的结构相反。
您可以通过多种方式表示和反序列化:
将MenuItem
定义为MenuItem
类型词典列表的子类:
public class MenuItem : List<Dictionary<string, MenuItem>>
{
}
Json.NET将能够开箱即用反序列化:
var root = JsonConvert.DeserializeObject<MenuItem>(json);
将您的MenuItem
定义为包含MenuItem
类型的词典列表:
[JsonConverter(typeof(MenuItemConverter))]
class MenuItem
{
public Dictionary<string, MenuItem> [] Items;
}
您需要一个自定义转换器,以便将Items
冒充JSON中的一个级别:
public class MenuItemConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(MenuItem);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var items = serializer.Deserialize<Dictionary<string, MenuItem>[]>(reader);
return new MenuItem { Items = items };
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var item = (MenuItem)value;
serializer.Serialize(writer, item.Items);
}
}
再次反序列化:
var root = JsonConvert.DeserializeObject<MenuItem>(json);
如果您真的希望数据模型是列表而不是字典列表,则需要在读取和写入时重构数据模型:
[JsonConverter(typeof(MenuItemConverter))]
class MenuItem
{
public MenuItem() { this.Items = new Dictionary<string, List<MenuItem>>(); }
public Dictionary<string, List<MenuItem>> Items;
}
public static class DictionaryExtensions
{
public static void Add<TKey, TValueList, TValue>(this IDictionary<TKey, TValueList> listDictionary, TKey key, TValue value)
where TValueList : IList<TValue>, new()
{
if (listDictionary == null)
throw new ArgumentNullException();
TValueList values;
if (!listDictionary.TryGetValue(key, out values))
listDictionary[key] = values = new TValueList();
values.Add(value);
}
public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(TKey key, TValue value)
{
var dict = new Dictionary<TKey, TValue>();
dict[key] = value;
return dict;
}
}
public class MenuItemConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(MenuItem);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var items = serializer.Deserialize<Dictionary<string, MenuItem>[]>(reader);
var menuItem = new MenuItem();
foreach (var pair in items.SelectMany(d => d))
menuItem.Items.Add(pair.Key, pair.Value);
return menuItem;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var menuItem = (MenuItem)value;
if (menuItem.Items == null)
writer.WriteNull();
else
{
var list = menuItem.Items.SelectMany(p => p.Value.Select(m => DictionaryExtensions.ToDictionary(p.Key, m)));
serializer.Serialize(writer, list);
}
}
}
然后
var root = JsonConvert.DeserializeObject<MenuItem>(json);