TeKrop / overfast-api

⚡ Unofficial Overwatch 2 API, built with FastAPI, provides data on heroes, game modes, maps, and player careers
https://overfast-api.tekrop.fr
MIT License
107 stars 13 forks source link

Missing some hero-data #34

Closed Backxtar closed 1 year ago

Backxtar commented 1 year ago

First of all - really nice api!

But can you provide some more informations about the heroes? First of all can you create an endpoint where you can fetch all hero specific data with 1 api call? Atm i need to loop threw each hero to get the complete data. E.g. heroes/ana -> then heroes/ashe etc.

Maybe an endpoint heroes/all would be nice.

I have created an external json with some more informations needed for the heroes. Would be really nice if this can be integraded into the normal heroes/all - heroes/ana request


[
    {
        "name": "Ana",
        "totalhp": 200,
        "hp": 200,
        "armor": 0,
        "shield": 0,
        "abilities": [
            {
                "name": "Biotic Rifle",
                "thumbnail": "https://images.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/bltc56d4d9789a018d0/63390487ed7dcc6a0028039c/ANA_BIOTICRIFLE.jpg",
                "video": "https://assets.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/blt90138e57c4b91c94/6339047e64fe5a7d4481a05c/OVERWATCH_WEBSITE_CHARACTER_CAPTURE_AnaBioticRifle_WEB_16x9_1920x1080p30_WEBM.webm"
            },
            {
                "name": "Sleep Dart",
                "thumbnail": "https://images.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/bltb27e2783f517c7fe/63390487e3c2a2741688cba3/ANA_SLEEPDART.jpg",
                "video": "https://assets.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/bltb6b9ecf5d9a2ec69/6339047ef87c00687e8ef222/OVERWATCH_WEBSITE_CHARACTER_CAPTURE_AnaSleepDart_WEB_16x9_1920x1080p30_WEBM.webm"
            },
            {
                "name": "Biotic Grenade",
                "thumbnail": "https://images.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/bltcd66dcc6eb196187/633904873922a2677fc88cfa/ANA_BIOTICGRENADE.jpg",
                "video": "https://assets.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/blt73fcfa06c4272760/6339047d3922a2677fc88cf6/OVERWATCH_WEBSITE_CHARACTER_CAPTURE_AnaBioticGrenade_WEB_16x9_1920x1080p30_WEBM.webm"
            },
            {
                "name": "Nano Boost",
                "thumbnail": "https://images.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/blt5901c5f790bb82f9/63390487da1d806602f83eee/ANA_NANOBOOST.jpg",
                "video": "https://assets.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/blt557e93a659cf572c/6339047e1a0b5e7d3d1ec595/OVERWATCH_WEBSITE_CHARACTER_CAPTURE_AnaNanoBoost_WEB_16x9_1920x1080p30_WEBM.webm"
            }
        ]
    },
    {
        "name": "Ashe",
        "totalhp": 200,
        "hp": 200,
        "armor": 0,
        "shield": 0,
        "abilities": [
            {
                "name": "The Viper",
                "thumbnail": "https://images.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/bltde449a1db082c1a1/633904ac64fe5a7d4481a060/ASHE_THE_VIPER.jpg",
                "video": "https://assets.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/bltfb9b1667be81b34b/633904bab8dbde69f52798ee/OVERWATCH_WEBSITE_CHARACTER_CAPTURE_AsheTheViper_WEB_16x9_1920x1080p30_WEBM.webm" 
            },
            {
                "name": "Coach Gun",
                "thumbnail": "https://images.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/blt0f6057298d1c0012/633904ac3922a2677fc88cfe/ASHE_COACH_GUN.jpg",
                "video": "https://assets.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/blt65112ab5e888622d/633904b91a0b5e7d3d1ec599/OVERWATCH_WEBSITE_CHARACTER_CAPTURE_AsheCoachGun_WEB_16x9_1920x1080p30_WEBM.webm"
            },
            {
                "name": "Dynamite",
                "thumbnail": "https://images.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/bltbbcb722a61594c10/633904acf87c00687e8ef226/ASHE_DYNAMITE.jpg",
                "video": "https://assets.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/blt9de32278cc1b4ea0/633904ba399a07678557c13d/OVERWATCH_WEBSITE_CHARACTER_CAPTURE_AsheDynamite_WEB_16x9_1920x1080p30_WEBM.webm"
            },
            {
                "name": "B.O.B.",
                "thumbnail": "https://images.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/blt171114cdbf544989/633904aced7dcc6a002803a0/ASHE_BOB.jpg",
                "video": "https://assets.blz-contentstack.com/v3/assets/blt2477dcaf4ebd440c/bltc1dff03c9903dad0/633904baec7e18758be51042/OVERWATCH_WEBSITE_CHARACTER_CAPTURE_AsheBOB_WEB_16x9_1920x1080p30_WEBM.webm"
            }
        ]
    },
    {

    }
]
TeKrop commented 1 year ago

Hello,

Thank you 😄 It's a good suggestion, I think I'll do the following :

I'll keep you updated here 😉

Backxtar commented 1 year ago

yeah i really like it :) Here is a video from the app ill programming right now :) - will be available for iOS and Android. Link

Backxtar commented 1 year ago

Btw the video + thumbnail would be very nice :) - i would say the webm version is better than the mp4

TeKrop commented 1 year ago

Oh very nice app you have here, can't wait to try it ! When you'll publish it (and/or the source code), don't hesitate to share the link with me, I'll gladly add your project in the README if you're OK with it (🚀 Community projects section)

Backxtar commented 1 year ago

ye the code wont be official but its free 4 all :) so remeber herodata (health shield etc)

thumbnails and videos for the skills (from the offical website :) i can give you the links :))

TeKrop commented 1 year ago

Health, armor and shields are OK (dev in progress), and i'll take a look for the thumbnails and videos for the skills, I should be able to retrieve them directly, I'll keep you updated ;)

Backxtar commented 1 year ago

Ah nice :) so ill keep working on the profile / stats page and do the heroes / maps etc later :)

Backxtar commented 1 year ago

Btw: here is a screen of the profile page :) http://i.epvpimg.com/K0nNcab.png

TeKrop commented 1 year ago

I made the update about heroes HP and abilities videos in the last release : https://github.com/TeKrop/overfast-api/releases/tag/v2.15.0

You'll find the new data in hitpoints and abilities[].video fields, I'll let you check the updated documentation and an example with Ana :

I'll let this issue opened while I'll be working on exposing more data in the general /heroes endpoint as discussed earlier 👍

Backxtar commented 1 year ago

Nice! There is one more thing i have to add. At the player stats summary for the heroes -> can u add a hero key for filtering the list? Cant filter the list for a specific hero because you dont have any unique key :)

Backxtar commented 1 year ago

i mean like this

"heroes": {
    "ana": {
      "key": "ana", <- this line is missing
      "games_played": 37,
      "time_played": 18032,
      "winrate": 48.65,
      "kda": 1.63,
      "total": {
        "eliminations": 206,
        "assists": 142,
        "deaths": 214,
        "damage": 98563,
        "healing": 190320
      },
      "average": {
        "eliminations": 6.85,
        "assists": 4.72,
        "deaths": 7.12,
        "damage": 3279.6,
        "healing": 6332.74
      }
    }
}

Otherwise you cant filter the list for hero-data because you cant filter for any attribute specific for that hero :)

Also which timeformat is that: "time_played": 172937 ?

TeKrop commented 1 year ago

At the player stats summary for the heroes -> can u add a hero key for filtering the list? Cant filter the list for a specific hero because you dont have any unique key :)

I don't understand your issue here 🤔 You should be able to use the key referencing the object in your code ("ana": {...}), without me needing to add a key in the object, I would find it superfluous 😅 Maybe I'm missing a point, don't hesitate to give me more precision if you think this is the case 👍

Also which timeformat is that: "time_played": 172937 ?

As stated in the introduction on the main documentation page, it's in seconds 😉

First of all can you create an endpoint where you can fetch all hero specific data with 1 api call? Atm i need to loop threw each hero to get the complete data. E.g. heroes/ana -> then heroes/ashe etc.

Finally, regarding this main topic, I'm starting to wonder if this is really necessary 🤔

Don't hesitate to give me some details and arguments, I will be happy to discuss about it 😄

Backxtar commented 1 year ago

my current status: https://streamable.com/dpbfl7

and no i cant search for the "key" because:

class Heroes {
  DataBlueprint? ana;
  DataBlueprint? ashe;
  DataBlueprint? baptiste;
  DataBlueprint? bastion;
  DataBlueprint? brigitte;
  DataBlueprint? cassidy;
  DataBlueprint? dva;
  DataBlueprint? doomfist;
  DataBlueprint? echo;
  DataBlueprint? lifeweaver; // <- This data is missing in stats summary
  DataBlueprint? genji;
  DataBlueprint? hanzo;
  DataBlueprint? junkerQueen;
  DataBlueprint? junkrat;
  DataBlueprint? kiriko;
  DataBlueprint? lucio;
  DataBlueprint? mei;
  DataBlueprint? mercy;
  DataBlueprint? moira;
  DataBlueprint? orisa;
  DataBlueprint? pharah;
  DataBlueprint? ramattra;
  DataBlueprint? reaper;
  DataBlueprint? reinhardt;
  DataBlueprint? roadhog;
  DataBlueprint? sigma;
  DataBlueprint? soldier76;
  DataBlueprint? sojourn;
  DataBlueprint? sombra;
  DataBlueprint? symmetra;
  DataBlueprint? torbjorn;
  DataBlueprint? tracer;
  DataBlueprint? widowmaker;
  DataBlueprint? winston;
  DataBlueprint? wreckingBall;
  DataBlueprint? zarya;
  DataBlueprint? zenyatta;
 }

They have all the same structure, i cant check for variable names :). I can check for null, but i need the key inside to get a reference to the heroes avatar etc from my other list :)

Btw. the lifeweaver stats are missing :)

Ah and no its not that terrible to make x calls to the api. i mean i fetch them async :) and without loading time i dont need a loading-screen 👯 . You dont need to make an extra endpoint for that :)

TeKrop commented 1 year ago

They have all the same structure, i cant check for variable names :). I can check for null, but i need the key inside to get a reference to the heroes avatar etc from my other list :)

Hmm 🤔 Why can't you check by variable name ? Isn't there another way for you to retrieve the JSON from the API and store the information ? Can't you just loop over the keys/properties + values ? 🤔

Also, I can see you have some values which are different from the ones exposed by the API, junkerQueen instead of junker-queen, soldier76 instead of soldier-76, does it mean that you're defining the name somewhere, or is there some sort of conversion ? I don't know the language/framework you're using, but it seems weird that you don't have a way to use keys/properties from an object 😅 I find it superfluous to put it both as an object "key", and in the "key" property along with the statistics values 😅

Btw. the lifeweaver stats are missing :)

It means you didn't play Lifeweaver in QP or Ranked this season. If you have no stat on a specific hero, it's not here at all, that's why it's not displayed as required in the documentation

Ah and no its not that terrible to make x calls to the api. i mean i fetch them async :) and without loading time i dont need a loading-screen 👯 . You dont need to make an extra endpoint for that :)

OK, thank you for your feedback, if it's working fine i'll not make an extra endpoint there, don't hesitate to tell me if you encounter any issue with the existing ones :)

Backxtar commented 1 year ago

Nah i cant filter for variable names (Got a list of off and need to loop threw it) - so i need to check data with a machting key (profilepic from herodata - ranked stats from other list | key: ana - ana for e.g.)

Also the webm format was not a good idea - mp4 is a better format but apple does not support webm yet 🤯

I mean something like

{
  "name": "Ana", <-- name.toLowerCase() = key
  "description": "One of the founding members of Overwatch, Ana uses her skills and expertise to defend her home and the people she cares for.",
  "portrait": ["https://d15f34w2p8l1cc.cloudfront.net/overwatch/3429c394716364bbef802180e9763d04812757c205e1b4568bc321772096ed86.png"](https://d15f34w2p8l1cc.cloudfront.net/overwatch/3429c394716364bbef802180e9763d04812757c205e1b4568bc321772096ed86.png),
  "role": "support",
  "location": "Cairo, Egypt",
  "hitpoints": {
    "health": 200,
    "shields": 0,
    "armor": 0,
    "total": 200
  },
...
}

and in the ranked hero stats

  "heroes": {
    "ana": {
      "key": "ana", <-- This key
      "games_played": 56,
      "time_played": 26889,
      "winrate": 46.43,
      "kda": 2.72,
      "total": {
        "eliminations": 435,
        "assists": 282,
        "deaths": 264,
        "damage": 152088,
        "healing": 354998
      },
      "average": {
        "eliminations": 9.71,
        "assists": 6.29,
        "deaths": 5.89,
        "damage": 3393.69,
        "healing": 7921.41
      }
    },
    ...
}

Nah i cant filter for variable names (Got a list of off and need to loop threw it) - so i need to check data with a machting key (profilepic from herodata - ranked stats from other list | key: ana - ana for e.g.)

Add herokey to ranked stats

Also the webm format was not a good idea - mp4 is a better format but apple does not support webm yet 🤯

Use mp4 instead of webm (only Android supports webm atm.)

Some herodata is wrong

Wrecking-Ball has 700 hp (shield + armor)

Backxtar commented 1 year ago

Can you provide these two changes? :3 - i mean the wrecking ball is maybe just not updated yet on the page you getting the data from :)

With the mp4 video the heroes page is finished then :)

Backxtar commented 1 year ago

Also, I can see you have some values which are different from the ones exposed by the API, junkerQueen instead of junker-queen, soldier76 instead of soldier-76, does it mean that you're defining the name somewhere, or is there some sort of conversion ? I don't know the language/framework you're using, but it seems weird that you don't have a way to use keys/properties from an object 😅 I find it superfluous to put it both as an object "key", and in the "key" property along with the statistics values 😅

These are not the strings i get from the api, i convert the json to an array of objects :) - and objects cant be named with special letters. The values have just names :) but thats the problem :) i cant filter the list by object names, i only can loop threw it and check for a specific key :)

TeKrop commented 1 year ago

These are not the strings i get from the api, i convert the json to an array of objects :) - and objects cant be named with special letters. The values have just names :) but thats the problem :) i cant filter the list by object names, i only can loop threw it and check for a specific key :)

Hmm if you're doing some kind of conversion, you may have a solution : while doing the conversion from JSON ({"junker-queen": {...}}) to an object named junkerQueen, can't you add the "junker-queen" key into the object ? Or even before doing the conversion ? Or if you're looking for a way to loop over attributes of an object in Swift (I guess you're using this language for Apple's ecosystem), here is an example of discussion on Stack Overflow which may help you : https://stackoverflow.com/questions/25463146/iterate-over-object-class-attributes-in-swift You'll just have to add the property while looping over DataBlueprint list 🤔

Sorry for insisting on this, but as it's very simple to do it in other common languages I know (Python, JS, PHP, etc.), I don't understand why it wouldn't be possible with Swift which is quite a popular language, and I would be very surprised 😅 Also, I wouldn't want you to be blocked one day if you have to deal with another API for another project with a similar problematic, and the developer can't be reached as easily and/or the API is handled by a private company which will not do any change easily 🙈 So I'm trying to find solutions with you, as we're talking about data which is already in the returned response 😅

Also the webm format was not a good idea - mp4 is a better format but apple does not support webm yet 🤯

Ah 🙈 I updated the API with both formats, API users will be able to chose the one they prefer 😉 image

Wrecking-Ball has 700 hp (shield + armor)

You're right, thank you for the feedback, I just fixed it 👍 In fact the data is located in the project directly, I don't have an external source on which I can get this data easily 😅 You can find it here : https://github.com/TeKrop/overfast-api/blob/main/app/data/heroes_stats.csv

Backxtar commented 1 year ago

Hmm if you're doing some kind of conversion, you may have a solution : while doing the conversion from JSON ({"junker-queen": {...}}) to an object named junkerQueen, can't you add the "junker-queen" key into the object ? Or even before doing the conversion ? Or if you're looking for a way to loop over attributes of an object in Swift (I guess you're using this language for Apple's ecosystem), here is an example of discussion on Stack Overflow which may help you : https://stackoverflow.com/questions/25463146/iterate-over-object-class-attributes-in-swift You'll just have to add the property while looping over DataBlueprint list 🤔

Please just add the herokey to the herostats :) its really way easier to loop threw it. Otherwise i have this ugly function in there. Also can u convert the heroes section to a list? Would be way easier for all to convert it. Otherwise they have to do a list manually. The list is really important for an app. I need to build the pages dynamically. otherwise i have to set a fixed number of heros because i cant loop threw an object. Without a list i have to check every hero / 37 heroes ^^. Thats not smart.

class OWPlayerStats {
  DataBlueprint? general;
  Roles? roles;
  Heroes? _heroes;
  List<DataBlueprint> heroes = List<DataBlueprint>.empty(growable: true);

  OWPlayerStats({this.general, this.roles});

  OWPlayerStats.fromJson(Map<String, dynamic> json) {
    general = json['general'] != null
        ? DataBlueprint.fromJson(json['general'])
        : null;
    roles = json['roles'] != null ? Roles.fromJson(json['roles']) : null;
    _heroes = json['heroes'] != null ? Heroes.fromJson(json['heroes']) : null;
    _loopHeroes();
    _heroes = null;
  }

  void _loopHeroes() {
    _addHeroToList(_heroes!.ana);
    _addHeroToList(_heroes!.ashe);
    _addHeroToList(_heroes!.baptiste);
    _addHeroToList(_heroes!.bastion);
    _addHeroToList(_heroes!.brigitte);
    _addHeroToList(_heroes!.cassidy);
    _addHeroToList(_heroes!.doomfist);
    _addHeroToList(_heroes!.dva);
    _addHeroToList(_heroes!.echo);
    _addHeroToList(_heroes!.genji);
    _addHeroToList(_heroes!.hanzo);
    _addHeroToList(_heroes!.junkerQueen);
    _addHeroToList(_heroes!.junkrat);
    _addHeroToList(_heroes!.kiriko);
    _addHeroToList(_heroes!.lifeweaver);
    _addHeroToList(_heroes!.lucio);
    _addHeroToList(_heroes!.mei);
    _addHeroToList(_heroes!.mercy);
    _addHeroToList(_heroes!.moira);
    _addHeroToList(_heroes!.orisa);
    _addHeroToList(_heroes!.pharah);
    _addHeroToList(_heroes!.ramattra);
    _addHeroToList(_heroes!.reaper);
    _addHeroToList(_heroes!.reinhardt);
    _addHeroToList(_heroes!.roadhog);
    _addHeroToList(_heroes!.sigma);
    _addHeroToList(_heroes!.sojourn);
    _addHeroToList(_heroes!.soldier76);
    _addHeroToList(_heroes!.sombra);
    _addHeroToList(_heroes!.symmetra);
    _addHeroToList(_heroes!.torbjorn);
    _addHeroToList(_heroes!.tracer);
    _addHeroToList(_heroes!.widowmaker);
    _addHeroToList(_heroes!.winston);
    _addHeroToList(_heroes!.wreckingBall);
    _addHeroToList(_heroes!.zarya);
    _addHeroToList(_heroes!.zenyatta);
  }

  void _addHeroToList(DataBlueprint? hero) {
    if (hero != null) heroes.add(hero);
  }
}

Json like this:

"heroes": [
   {
      "key": "ana",
      "games_played": 57,
      "time_played": 27369,
      "winrate": 47.37,
      "kda": 2.77,
      "total": {
        "eliminations": 459,
        "assists": 290,
        "deaths": 270,
        "damage": 156057,
        "healing": 357333
      },
      "average": {
        "eliminations": 10.06,
        "assists": 6.36,
        "deaths": 5.92,
        "damage": 3421.18,
        "healing": 7833.67
      }
   },
   {
      ...
   }
]

Btw thumbnails and videos work like a charm :) Watch: https://streamable.com/9sy2on

TeKrop commented 1 year ago

In order to meet your needs :

I was curious and asked ChatGPT to give me a hand in order to convert the input provided by the API into the one you're expecting, and it answered to me this piece of Swift code which seems to be working (tested with Replit, an online IDE) :

import Foundation

let json = """
{
    "heroes": {
        "ana": {
            "games_played": 1219,
            "time_played": 570188,
            "winrate": 46.92,
            "kda": 2.42,
            "total": {
                "eliminations": 9622,
                "assists": 7273,
                "deaths": 6972,
                "damage": 3341466,
                "healing": 6460895
            },
            "average": {
                "eliminations": 10.13,
                "assists": 7.65,
                "deaths": 7.34,
                "damage": 3516.17,
                "healing": 6798.7
            }
        },
        "ashe": {
            "games_played": 2,
            "time_played": 950,
            "winrate": 50.0,
            "kda": 2.29,
            "total": {
                "eliminations": 32,
                "assists": 0,
                "deaths": 14,
                "damage": 13873,
                "healing": 0
            },
            "average": {
                "eliminations": 20.21,
                "assists": 0.0,
                "deaths": 8.84,
                "damage": 8761.89,
                "healing": 0.0
            }
        }
    }
}
"""

if let data = json.data(using: .utf8),
   let jsonObj = try? JSONSerialization.jsonObject(with: data),
   let heroes = (jsonObj as? [String: Any])?["heroes"] as? [String: Any] {

    let heroList = heroes.map { (key, value) -> [String: Any] in
        var hero = value as? [String: Any] ?? [:]
        hero["key"] = key
        return hero
    }

    let outputJSON: [String: Any] = ["heroes": heroList]

    if let outputData = try? JSONSerialization.data(withJSONObject: outputJSON),
       let outputString = String(data: outputData, encoding: .utf8) {
        print(outputString)
    }
}

I don't have any knowledge in Swift, so I guess there are cleaner ways to do the job, but at least it's working and you're not limited with the "ugly function" you have in your code. And it will work even if new heroes are coming into the API in the future :) Don't hesitate to tell me if it's working well for you on your dev environment ^^

Btw thumbnails and videos work like a charm :) Watch: https://streamable.com/9sy2on

Ooh very nice result you have here, good job 😄

Backxtar commented 1 year ago

In order to meet your needs :

  • having the key in the object at the same level of games_played, etc.
  • having a list instead of an object with hero keys

Yes and Yes (Having a list for the hero stats would make life way easier because you dont have allways the same amount on heroes you are playing) :)

I was curious and asked ChatGPT to give me a hand in order to convert the input provided by the API into the one you're expecting, and it answered to me this piece of Swift code which seems to be working (tested with Replit, an online IDE) :

I don't have any knowledge in Swift, so I guess there are cleaner ways to do the job, but at least it's working and you're not limited with the "ugly function" you have in your code. And it will work even if new heroes are coming into the API in the future :) Don't hesitate to tell me if it's working well for you on your dev environment ^^

Im not using swift :D im using dart and flutter for the app :) - because its cross plattform. Android and iOS.

TeKrop commented 1 year ago

Yes and Yes (Having a list for the hero stats would make life way easier because you dont have allways the same amount on heroes you are playing) :)

I guess this is more convenient in your case, but I'm not sure it always will for everyone. I had the choice when creating this endpoint, and I chose the other way. I know some people are already using this endpoint when looking at access logs, and no one told me it was not handy and that I should switch to a list 😅 I'm always trying to give the data in the most exploitable way, and then it's the responsability of the app/website developer to use the API as it's exposed and adapt : as long as all the needed data is here, I assume I've done my part 🤔

Im not using swift :D im using dart and flutter for the app :) - because its cross plattform. Android and iOS.

Ah I didn't know 🙈 Cross platform dev is a good choice 👍 Well then, I asked the same thing in Dart to ChatGPT and tested with Replit, here is a working piece of code which seems to be clean enough and will do the job 😉 You just have to add the dart:convert dependency in your project if it's not already done.

import 'dart:convert';

void main() {
  String jsonString = '''
    {
      "heroes": {
        "ana": {
          "games_played": 1219,
          "time_played": 570188,
          "winrate": 46.92,
          "kda": 2.42,
          "total": {
            "eliminations": 9622,
            "assists": 7273,
            "deaths": 6972,
            "damage": 3341466,
            "healing": 6460895
          },
          "average": {
            "eliminations": 10.13,
            "assists": 7.65,
            "deaths": 7.34,
            "damage": 3516.17,
            "healing": 6798.7
          }
        },
        "ashe": {
          "games_played": 2,
          "time_played": 950,
          "winrate": 50.0,
          "kda": 2.29,
          "total": {
            "eliminations": 32,
            "assists": 0,
            "deaths": 14,
            "damage": 13873,
            "healing": 0
          },
          "average": {
            "eliminations": 20.21,
            "assists": 0.0,
            "deaths": 8.84,
            "damage": 8761.89,
            "healing": 0.0
          }
        }
      }
    }
  ''';

  Map<String, dynamic> jsonMap = json.decode(jsonString);

  List<Map<String, dynamic>> heroesList = [];

  jsonMap['heroes'].forEach((key, value) {
    value['key'] = key;
    heroesList.add(value);
  });

  Map<String, List<Map<String, dynamic>>> result = {'heroes': heroesList};

  String resultString = json.encode(result);

  print(resultString);
}

In general, as long as it's free, don't hesitate to use ChatGPT or equivalent AI tools to help you when you're blocked with some issues in your code for your personal projects, or when you're learning things related to a programming language. It's very powerful to have a start with a new language or even to have some leads on solving a problem. I shared with you some pieces of Swift and Dart codes, which took me no more than 5 min, even if I never learned how to use these languages 😅

Backxtar commented 1 year ago

Ahh thanks to you i got a solution :)

class OWPlayerStats {
  DataBlueprint? general;
  Roles? roles;
  List<DataBlueprint>? heroes;

  OWPlayerStats({this.general, this.roles, this.heroes});

  OWPlayerStats.fromJson(Map<String, dynamic> json) {
    general = json['general'] != null
        ? DataBlueprint.fromJson(json['general'])
        : null;
    roles = json['roles'] != null ? Roles.fromJson(json['roles']) : null;
    heroes = json['heroes'] != null ? _getHeroes(json['heroes']) : null;
  }

  List<DataBlueprint> _getHeroes(Map<String, dynamic> json) {
    List<DataBlueprint> heroes = List<DataBlueprint>.empty(growable: true);
    json.forEach((key, value) {
      DataBlueprint hero = DataBlueprint.fromJson(value);
      hero.key = key;
      heroes.add(hero);
    });
    return heroes;
  }
}

Now its a dynamic list of my object :)

The key is exactly the key from the heroes api endpoint?

TeKrop commented 1 year ago

Ahh thanks to you i got a solution :) Now its a dynamic list of my object :)

Nice solution you have there, you're welcome 😉 Sorry again for insisting on this, in the end we came up with a solution, and if some day you encounter a similar issue with another API, you'll know how to handle it 😄

The key is exactly the key from the heroes api endpoint ?

Yes exactly ! I'm using the same enumeration all across my code and the exposed endpoints 😉

Can I consider this issue as solved then ? I think that if you find out another issue anywhere else, it will be better to open a new issue rather than continuing comments here 🙈

Backxtar commented 1 year ago

Ye all good right now 👍