简体   繁体   中英

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

        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:

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. 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.

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 :

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:

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.

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; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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