[英]Cannot deserialize the current json object into ObservableCollection
(帖子底部的完整错误消息)
我知道这已经在其他几篇文章中进行了讨论,但是这些文章中提供的修复程序似乎对我不起作用。
我在下面提供所有代码。 反序列化在方法parseSpellData()
。
JSON示例:
{
"_id": "58c9eb75c9e7ce9f7214efaa",
"index": 1,
"name": "Acid Arrow",
"desc": [
"A shimmering green arrow streaks toward a target within range and bursts in a spray of acid. Make a ranged spell attack against the target. On a hit, the target takes 4d4 acid damage immediately and 2d4 acid damage at the end of its next turn. On a miss, the arrow splashes the target with acid for half as much of the initial damage and no damage at the end of its next turn."
],
"higher_level": [
"When you cast this spell using a spell slot of 3rd level or higher, the damage (both initial and later) increases by 1d4 for each slot level above 2nd."
],
"page": "phb 259",
"range": "90 feet",
"components": [
"V",
"S",
"M"
],
"material": "Powdered rhubarb leaf and an adder’s stomach.",
"ritual": "no",
"duration": "Instantaneous",
"concentration": "no",
"casting_time": "1 action",
"level": 2,
"school": {
"url": "http://dnd5eapi.co/api/magic-schools/5",
"name": "Evocation"
},
"classes": [
{
"name": "Wizard",
"url": "http://dnd5eapi.co/api/classes/12"
}
],
"subclasses": [
{
"url": "http://dnd5eapi.co/api/subclasses/2",
"name": "Lore"
},
{
"url": "http://dnd5eapi.co/api/subclasses/4",
"name": "Land"
}
],
"url": "http://dnd5eapi.co/api/spells/1"
}
码:
class MainPageViewModel
{
public ObservableCollection<Spell> availableSpells { get; set; } = new ObservableCollection<Spell>();
public MainPageViewModel()
{
availableSpells = parseSpellData(getSpells());
}
public string getSpells()
{
string spells = string.Empty;
try
{
HttpWebRequest request = WebRequest.Create("http://dnd5eapi.co/api/Spells") as HttpWebRequest;
using (var response = request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
spells = reader.ReadToEnd();
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.WriteLine(spells);
return spells;
}
public ObservableCollection<Spell> parseSpellData(string listOfSpells)
{
ObservableCollection<Spell> parsedSpellData = JsonConvert.DeserializeObject<ObservableCollection<Spell>>(listOfSpells);
return parsedSpellData as ObservableCollection<Spell>;
}
}
public class School
{
public string url { get; set; }
public string name { get; set; }
}
public class Class
{
public string name { get; set; }
public string url { get; set; }
}
public class Subclass
{
public string url { get; set; }
public string name { get; set; }
}
public class Spell
{
public string _id { get; set; }
public int index { get; set; }
public string name { get; set; }
public List<string> desc { get; set; }
public List<string> higher_level { get; set; }
public string page { get; set; }
public string range { get; set; }
public List<string> components { get; set; }
public string material { get; set; }
public string ritual { get; set; }
public string duration { get; set; }
public string concentration { get; set; }
public string casting_time { get; set; }
public int level { get; set; }
public School school { get; set; }
public List<Class> classes { get; set; }
public List<Subclass> subclasses { get; set; }
public string url { get; set; }
}
PM汽化错误
无法将当前JSON对象(例如{“ name”:“ value”})反序列化为类型'System.Collections.ObjectModel.ObservableCollection´1 [NInterpret.interpretedObject]',因为该类型需要JSON数组(例如[1,2, 3])正确反序列化。 要解决此错误,可以将JSON更改为JSON数组(例如[1,2,3]),也可以更改反序列化类型,使其成为普通的.NET类型(例如,不是整数之类的原始类型,而不是一个集合类型)可以从JSON对象反序列化likan一个数组或List)。
问题是您的JSON不是数组,它是一个包含数组值属性的对象。 如果您使用https://jsonformatter.curiousconcept.com/格式化http://dnd5eapi.co/api/Spells返回的JSON,则可以更清楚地看到:
{
"count":305,
"results":[
{
"name":"Acid Arrow",
"url":"http://www.dnd5eapi.co/api/spells/1"
},
{
"name":"Acid Splash",
"url":"http://www.dnd5eapi.co/api/spells/2"
}
// Additional entries omitted
]
}
因此,您需要反序列化到包含"results"
集合的模型,而不是集合本身。 一种简单的方法是使用JsonConvert.DeserializeAnonymousType()
指定包装程序根对象:
public ObservableCollection<Spell> parseSpellData(string listOfSpells)
{
var parsedSpellData = JsonConvert.DeserializeAnonymousType(listOfSpells, new { results = (ObservableCollection<Spell>)null });
return parsedSpellData.results;
}
工作提琴#1 。
当然,您也可以为根指定一个显式类型-实际上,如果将[JsonProperty("results")]
到availableSpells
则MainPageViewModel
可以用于此目的:
class MainPageViewModel
{
[JsonProperty("results")]
public ObservableCollection<Spell> availableSpells { get; set; } = new ObservableCollection<Spell>();
public MainPageViewModel()
{
JsonConvert.PopulateObject(getSpells(), this);
}
示例工作提琴#2 。
实际上,您的数据模型似乎具有JSON中不存在的许多属性,其中返回的"results"
数组中的返回对象仅包含"name"
和"url"
属性。 您确定为此特定API使用的数据模型正确吗?
更新资料
您问题中发布的JSON似乎由返回结果中列出的特定拼写API URL返回,例如http://www.dnd5eapi.co/api/spells/1 ,它进一步对应于您的Spell
类型。 如果您希望一次获取所有拼写数据,则可以引入以下类型
public class NameAndUri
{
public string url { get; set; }
public string name { get; set; }
}
public class NameAndUri<T> : NameAndUri
{
public T Deserialize()
{
return JsonExtensions.DeserializeFromUri<T>(url);
}
}
public static partial class JsonExtensions
{
public static T DeserializeAnonymousTypeFromUri<T>(string uri, T anonymousTypeObject)
{
return DeserializeFromUri<T>(uri);
}
public static T DeserializeFromUri<T>(string uri)
{
HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
using (var response = request.GetResponse())
using (var reader = new StreamReader(response.GetResponseStream()))
using (var jsonReader = new JsonTextReader(reader))
{
return JsonSerializer.CreateDefault().Deserialize<T>(jsonReader);
}
}
}
并如下修改MainPageViewModel
:
class MainPageViewModel
{
public const string spellUri = "http://dnd5eapi.co/api/Spells";
public ObservableCollection<Spell> availableSpells { get; set; } // = new ObservableCollection<Spell>();
public MainPageViewModel()
{
availableSpells = parseSpellData(spellUri);
}
static ObservableCollection<Spell> parseSpellData(string spellUri)
{
var parsedSpellData = JsonExtensions.DeserializeAnonymousTypeFromUri(spellUri, new { results = (List<NameAndUri<Spell>>)null });
var query = parsedSpellData.results.Select(s => s.Deserialize());
return new ObservableCollection<Spell>(query);
}
}
笔记:
正如Newtonsoft中推荐的那样:性能提示我直接从响应流中反序列化,而不是加载到中间string
。
您可能想用NameAndUri<T>
替换School
, Class
和Subclass
类型,以获得一些适当的T
如果一次加载所有咒语的性能不够好,请考虑使用异步解决方案 。
示例小提琴#3在https://dotnetfiddle.net/上超时,但在本地工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.