【问题标题】:How to parse json and deserialize it to ObservableCollection of a class如何解析json并将其反序列化为类的ObservableCollection
【发布时间】:2021-02-27 06:55:39
【问题描述】:

我正在构建一个 Xamarinforms 应用程序,该应用程序使用 web 服务 api 来填充数据与权力的游戏演员。 API 将使用演员姓名、图片和舞台名称填写应用程序。

我正在尝试 解析 json 并反序列化为 CharacterClass 的 ObservableCollection (从此函数返回 Task

这是我得到的错误

无法将当前 JSON 对象(例如 {"name":"value"})反序列化为类型 'System.Collections.ObjectModel.ObservableCollection`1[GOTapp.CharacterClass]' 因为该类型需要 JSON 数组(例如 [1 ,2,3]) 以正确反序列化。 要修复此错误,要么将 JSON 更改为 JSON 数组(例如 [1,2,3]),要么将反序列化类型更改为普通的 .NET 类型(例如,不是像整数这样的原始类型,而不是像这样的集合类型可以从 JSON 对象反序列化的数组或列表。 JsonObjectAttribute 也可以添加到类型中以强制它从 JSON 对象反序列化。 路径“字符”,第 2 行,位置 16。

namespace GOTapp
{
    public class CharactersManager
    {
        public ObservableCollection<CharacterClass> characterList
        {
            get;
            set;
        }

    public class LogInResult
    {
        public string Name { get; set; }
        public string cityName { get; set; }
        public string img { get; set; }
        public string usrId { get; set; }
    }

    public string url = "https://raw.githubusercontent.com/jeffreylancaster/game-of-thrones/master/data/characters.json";
    HttpClient client = new HttpClient();


    public async Task<ObservableCollection<CharacterClass>> downloadData()
    {
        // Get data from provided web service
        // parse json and deserialize it to ObservableCollection of CharacterClass
        // return Task<ObservableCollection<CharacterClass>> from this function





        var json = await client.GetStringAsync(url);
        characterList = JsonConvert.DeserializeObject<ObservableCollection<CharacterClass>>(json);

        return characterList;
    }
    

    public void postActor()
    {
        var character = new CharacterClass
        {
            characterImageThumb = "https://images-na.ssl-images-amazon.com/images/M/MV5BNzI5MDg0ZDAtN2Y2ZC00MzU1LTgyYjQtNTBjYjEzODczZDVhXkEyXkFqcGdeQXVyNTg0Nzg4NTE@._V1._SX100_SY140_.jpg",
            characterName = "Aeron Greyjoy",
            actorName = "Michael Feast"
        };


        var content = JsonConvert.SerializeObject(character);
        client.PostAsync(url, new StringContent(content));

    }



}

}

这里是json的格式

{
   "characters":[
      {
         "characterName":"Addam Marbrand",
         "characterLink":"/character/ch0305333/",
         "actorName":"B.J. Hogg",
         "actorLink":"/name/nm0389698/"
      },
      {
         "characterName":"Aegon Targaryen",
         "houseName":"Targaryen",
         "royal":true,
         "parents":[
            "Elia Martell",
            "Rhaegar Targaryen"
         ],
         "siblings":[
            "Rhaenys Targaryen",
            "Jon Snow"
         ],
         "killedBy":[
            "Gregor Clegane"
         ]
      }
]
}

这里是json数据的链接 https://raw.githubusercontent.com/jeffreylancaster/game-of-thrones/master/data/characters.json

我将不胜感激任何形式的帮助

这是我的主页

namespace GOTapp

{ 公共部分类 MainPage : ContentPage {

    public ObservableCollection<CharacterClass> downloadedList;

    public CharactersManager manager = new CharactersManager();

    public MainPage()
    {
        InitializeComponent();
        actorlist.RowHeight = 50;

    }

    protected async override void OnAppearing()
    {
        if (downloadedList.Count == 0)
        {
            actorlist.ItemsSource = null;
            // call downloadData function from here.
            var list = await manager.downloadData();
            downloadedList = new ObservableCollection<CharacterClass>(list);
            actorlist.ItemsSource = downloadedList;
            

        }
        base.OnAppearing();
    }

    void actorlist_ItemSelected(System.Object sender, Xamarin.Forms.SelectedItemChangedEventArgs e)
    {
        // navigate to Detail Page and passing the selected character to detail page.

        manager.postActorList();
    }

}

}

这是我的。字符类.cs

   using System;
namespace GOTapp
{
    public class CharacterClass
    {
        public int id { get; set; }
        public string characterName { get; set; }
        public string actorName { get; set; }
        public string characterImageThumb { get; set; }





        public CharacterClass()
        {

        }
        
        // Version 2: add integer attribute for rating.
    }
}

【问题讨论】:

  • ObservableCollection改成IList
  • 指令要求返回 Task>。这有关系吗?
  • 你想看看我的角色等级吗?

标签: c# json api json-deserialization


【解决方案1】:

你可以使用下面的代码。

var characterList = JsonConvert.DeserializeObject<Example>(json);
ObservableCollection<CharacterClass> myCollection = new ObservableCollection<CharacterClass>(characterList.characters);

public class Example
{
    public IList<CharacterClass> characters { get; set; }
}

【讨论】:

  • 嗨,你能用我的代码详细说明一下吗?我尝试了各种实现,但仍然出现错误。
  • 指令要求返回 Task>。在您的解决方案中,我们现在是否返回和 IList?
  • JsonConvert.DeserializeObject>(响应);这不起作用:(
  • 是的,您可以尝试我的解决方案,它会起作用,您只需返回 mycollection。查看更新的答案。我已经用你的 json 测试过了
  • 你能把它打出来吗?由于某种原因它不起作用
【解决方案2】:

Json 的数据有一个非常烦人的问题。 HouseName 值同时具有字符串值和字符串数组值。我把它变成了一个对象,然后给了它两个单独的变量StringHouseNameArrayHouseName,每条记录中只有一个有一个值。

1.必修课

public class DataWeb
{
    public ObservableCollection<CharacterClass> Characters { get; set; }
}
public class CharacterClass
{
    public int id { get; set; }
    public string CharacterName { get; set; }
    public string StringHouseName { get; set; }
    public string[] ArrayHouseName { get; set; }
    public object HouseName
    {
       get
       {
          if (string.IsNullOrEmpty(StringHouseName))
             return ArrayHouseName;
          else
             return StringHouseName;
       }
       set
       {
           if (value is JArray)
           {
               JArray jArray = (JArray)value;
               ArrayHouseName = jArray.Select(ja => (string)ja).ToArray();
           }   
           else
               StringHouseName = (string)value;
       }
   }
   public string CharacterImageThumb { get; set; }
   public string CharacterImageFull { get; set; }
   public string CharacterLink { get; set; }
   public string ActorName { get; set; }
   public string ActorLink { get; set; }
   public bool kingsguard { get; set; }
   public bool Royal { get; set; }
   public string[] killedBy { get; set; }
   public string[] ParentOf { get; set; }

   public string[] Serves { get; set; }
   public string[] Siblings { get; set; }
   public string[] Killed { get; set; }
   public string[] Parents { get; set; }
   public string[] GuardedBy { get; set; }
   public string[] MarriedEngaged { get; set; }
   public string[] GuardianOf { get; set; }
   public string[] Allies { get; set; }
   public Actor[] Actors { get; set; }
}
public class Actor
{
    public string ActorName { get; set; }
    public string ActorLink { get; set; }
    public int[] SeasonsActive { get; set; }
}

2。现在使用和反序列化

public async Task<ObservableCollection<CharacterClass>> downloadData()
{
    var client = new HttpClient();
    var result = await client.GetAsync(@"https://raw.githubusercontent.com/jeffreylancaster/game-of-thrones/master/data/characters.json");
    var json = await result.Content.ReadAsStringAsync();

    DataWeb dataWeb = JsonConvert.DeserializeObject<DataWeb>(json);
    return dataWeb.Characters;
}

private async void button1_Click(object sender, EventArgs e)
{
   await Task.Run(() =>
   {
      var gameOfThrones = downloadData().Result;
   });
}

【讨论】:

  • 嗨,我应该为 DataWeb 导入什么库
  • 什么都没有。只需复制代码即可获得您想要的结果
猜你喜欢
  • 2020-07-13
  • 1970-01-01
  • 1970-01-01
  • 2015-01-09
  • 1970-01-01
  • 1970-01-01
  • 2015-06-03
  • 2015-09-21
  • 1970-01-01
相关资源
最近更新 更多