簡體   English   中英

無法將當前json對象反序列化為ObservableCollection

[英]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")]availableSpellsMainPageViewModel可以用於此目的:

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>替換SchoolClassSubclass類型,以獲得一些適當的T

  • 如果一次加載所有咒語的性能不夠好,請考慮使用異步解決方案

示例小提琴#3https://dotnetfiddle.net/上超時,但在本地工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM