我有一些如下所示的 json:
[
{
"MenuItem1": [
{ "SubItem1": [ ] },
{ "SubItem2": [ ] },
{ "SubItem3": [
{ "SubSubItem": [ ] }
]
}
]
},
{ "MenuItem2": [ ] }
]
这可以用以下 C# 数据结构表示:
class MenuItem
{
Dictionary<string, MenuItem[]> Items;
}
我尝试将其反序列化为
MenuItem[] roots = JsonConvert.DeserializeObject<MenuItem[]>(json);
但它不起作用,因为它不知道 Items
成员是该字典数据应该进行递归调用的位置。我怎样才能做到这一点?
最佳答案
您的基本问题是您的 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; }
您将需要一个自定义转换器来将 JSON 中的
Items
向上冒泡: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);
原型(prototype) fiddle showing all three .
关于json.net - 使用递归类型反序列化 json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34960853/