gpt4 book ai didi

c# - 使用 Json.Net 的多态 JSON 反序列化失败

转载 作者:可可西里 更新时间:2023-11-01 07:44:04 25 4
gpt4 key购买 nike

我正在尝试使用自定义 JsonConverter

将一些 JSON 反序列化为各种子类

我关注了this快到重点了。

我的抽象基类:

abstract class MenuItem
{
public String Title { get; set; }
public String Contents { get; set; }
public List<MenuItem> Submenus { get; set; }
public String Source { get; set; }
public String SourceType { get; set; }
public abstract void DisplayContents();
}

和我派生的 JsonConverter:

class MenuItemConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(MenuItem).IsAssignableFrom(objectType);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject item = JObject.Load(reader);
switch (item["SourceType"].Value<String>())
{
case SourceType.File: return item.ToObject<Menu.FileMenu>();
case SourceType.Folder: return item.ToObject<Menu.FolderMenu>();
case SourceType.Json: return item.ToObject<Menu.JsonMenu>();
case SourceType.RestGet: return item.ToObject<Menu.RestMenu>();
case SourceType.Rss: return item.ToObject<Menu.RssMenu>();
case SourceType.Text: return item.ToObject<Menu.TextMenu>();
case SourceType.Url: return item.ToObject<Menu.UrlMenu>();
default: throw new ArgumentException("Invalid source type");
}
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

SourceType 只是一个包含一些字符串常量的静态类。

JSON文件反序列化如下:

JsonConvert.DeserializeObject<MenuItem>(File.ReadAllText(menuPath), new MenuItemConverter());

现在,我的问题是每当我运行代码时都会收到以下错误:

An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code

Additional information: Could not create an instance of type ConsoleMenu.Model.MenuItem. Type is an interface or abstract class and cannot be instantiated. Path 'Submenus[0].Title', line 5, position 21.

有问题的 Json 文件如下所示:

{
"Title": "Main Menu",
"Submenus": [
{
"Title": "Submenu 1",
"Contents": "This is an example of the first sub-menu",
"SourceType": "Text"
},
{
"Title": "Submenu 2",
"Contents": "This is the second sub-menu",
"SourceType": "Text"
},
{
"Title": "GitHub System Status",
"Contents": "{\"status\":\"ERROR\",\"body\":\"If you see this, the data failed to load\"}",
"Source": "https://status.github.com/api/last-message.json",
"SourceType": "RestGet"
},
{
"Title": "TF2 Blog RSS",
"Contents": "If you see this message, an error has occurred",
"Source": "http://www.teamfortress.com/rss.xml",
"SourceType": "Rss"
},
{
"Title": "Submenus Test",
"Contents": "Testing the submenu functionality",
"Submenus": [
{
"Title": "Submenu 1",
"Contents": "This is an example of the first sub-menu",
"SourceType": "Text"
},
{
"Title": "Submenu 2",
"Contents": "This is the second sub-menu",
"SourceType": "Text"
}
]
}
],
"SourceType": "Text"
}

在我看来,它在反序列化嵌套对象时遇到了问题,我该如何解决这个问题?

最佳答案

首先,您的 json 中的菜单项“子菜单测试”缺少 SourceType

其次,您不应该简单地使用 ToObject,因为 Submenus 属性应该递归处理。

以下 ReadJson 将起作用:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
var sourceType = jObject["SourceType"].Value<string>();

object target = null;

switch (sourceType)
{
case SourceType.File:
target = new FileMenu(); break;
case SourceType.Folder:
target = new FolderMenu(); break;
case SourceType.Json:
target = new JsonMenu(); break;
case SourceType.RestGet:
target = new RestMenu(); break;
case SourceType.Rss:
target = new RssMenu(); break;
case SourceType.Text:
target = new TextMenu(); break;
case SourceType.Url:
target = new UrlMenu(); break;
default:
throw new ArgumentException("Invalid source type");
}

serializer.Populate(jObject.CreateReader(), target);

return target;
}

关于c# - 使用 Json.Net 的多态 JSON 反序列化失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29124126/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com