简体   繁体   English

将动态Json数据结构解析为对象C#/ dotnet核心

[英]Parsing Dynamic Json datastructure to object C# / dotnet core

I am trying to parse data from Riot API to C# objects https://developer.riotgames.com/api-methods/#lol-static-data-v1.2/GET_getChampionList 我正在尝试将Riot API中的数据解析为C#对象https://developer.riotgames.com/api-methods/#lol-static-data-v1.2/GET_getChampionList

        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        HttpResponseMessage response = await client.GetAsync("https://global.api.riotgames.com/api/lol/static-data/EUW/v1.2/champion?champData=allytips%2Cenemytips%2Cimage%2Ctags&dataById=true&api_key=###################");

        if (response.IsSuccessStatusCode)
        {
            var streamTask = response.Content.ReadAsStreamAsync();
            var stringJson = await response.Content.ReadAsStringAsync();
            var serializer = new DataContractJsonSerializer(typeof(ChampionWrapper));
            var champions = serializer.ReadObject(await streamTask) as ChampionWrapper;
        }

So far I am only getting the type and version converted. 到目前为止,我只转换了类型和版本。
The Data structure looks as following: 数据结构如下所示:

{
  "type": "champion",
  "version": "7.9.1",
  "data": {
    "89": {
      "id": 89,
      "key": "Leona",
      "name": "Leona",
      "title": "the Radiant Dawn",
      "image": {
        "full": "Leona.png",
        "sprite": "champion2.png",
        "group": "champion",
        "x": 0,
        "y": 0,
        "w": 48,
        "h": 48
      },
      "allytips": [
        "Lead the charge and mark your foes with Sunlight before your allies deal damage.",
        "Shield of Daybreak and Zenith Blade form a powerful offensive combo.",
        "You can absorb a huge amount of damage using Eclipse, but you must stay near enemies to gain the bonus duration."
      ],
      "enemytips": [
        "When Leona activates Eclipse, you have three seconds to get away from her before she deals damage.",
        "Only foes in the center of Solar Flare get stunned, so you can often avoid this if you're quick."
      ],
      "tags": [
        "Tank",
        "Support"
      ]
    },
    "110": {
      "id": 110,
      "key": "Varus",
      "name": "Varus",
      "title": "the Arrow of Retribution",
      "image": {
        "full": "Varus.png",
        "sprite": "champion3.png",
        "group": "champion",
        "x": 336,
        "y": 96,
        "w": 48,
        "h": 48
      },

So far I have a ChampionWrapper: 到目前为止,我有一个ChampionWrapper:

public class ChampionWrapper
{
    public string type { get; set; }
    public string version { get; set; }
    public List<ChampionData> data { get; set; }

    public ChampionWrapper()
    {

    }
}

List ChampionData is not getting populated. 列表ChampionData未填充。 Version and type is working. 版本和类型正常。

    public List<string> id {get;set;}
    public List<Champion> id { get; set; }
    public ChampionData()
    {

    }

Here is the champion object 这是冠军对象

    public string Id { get; set; }
    public string Name { get; set; }
    public string Title { get; set; }
    public List<string> AllyTips { get; set; }
    public List<string> EnemyTips { get; set; }
    public List<string> Tags { get; set; }

    public Champion()
    {

    }

My main problem is the dynamic datastruce 我的主要问题是动态数据结构

"data": {
    "89": { .... }
    "110": { .... }

The number is just the ID of the champion. 数字只是冠军的ID。

You are not using the correct class for deserializing your object. 您没有使用正确的类对对象进行反序列化。 The data property in your json is not a List , but more like a Dictionary : json中的data属性不是List ,而是更像Dictionary

public class ChampionWrapper
{
    public string type { get; set; }
    public string version { get; set; }
    public Dictionary<string, Champion> data { get; set; }
}

[Edit] [编辑]

I believe that you are complicating the way to deserialize the response from Json, instead of deserializing the response manually using DataContractSerializer you should use ReadAsAsync<T> extension method to obtain an object of your class: 我相信您正在复杂化从Json反序列化响应的方法,而不是使用DataContractSerializer手动反序列化响应,而应该使用ReadAsAsync<T>扩展方法来获取类的对象:

if(response.IsSuccessStatusCode)
{
    var champions = await response.Content.ReadAsAsync<ChampionWrapper>();
}

This extension method is found inside the Microsoft.AspNet.WebApi.Client nuget package , remember to add it before using it. 此扩展方法位于Microsoft.AspNet.WebApi.Client nuget包中 ,请记住在使用前将其添加。

Found solution: 找到的解决方案:

            DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings();
            settings.UseSimpleDictionaryFormat = true;

The whole thing: 整个东西:

        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        HttpResponseMessage response = await client.GetAsync("https://global.api.riotgames.com/api/lol/static-data/EUW/v1.2/champion?champData=allytips%2Cenemytips%2Cimage%2Ctags&dataById=true&api_key=###########");

        if (response.IsSuccessStatusCode)
        {
            DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings();
            settings.UseSimpleDictionaryFormat = true;

            var streamTask = response.Content.ReadAsStreamAsync();
            var stringJson = await response.Content.ReadAsStringAsync();
            var serializer = new DataContractJsonSerializer(typeof(ChampionWrapper), settings);
            var champions = serializer.ReadObject(await streamTask) as ChampionWrapper;
        }

And ofcourse changing list to Dictionary: 当然,将列表更改为字典:

public class ChampionWrapper
{
    public string type { get; set; }
    public string version { get; set; }
    public Dictionary<string, Champion> data { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM