Converting a Real Game Leaderboard API from JSON to Python

I run a small gamified fitness app on the side — workouts give XP, XP gives levels, and players can PVP each other on a live leaderboard. The backend is plain PHP with MySQL. Here is the actual shape of the JSON the ranking endpoint returns, and what I had to think about converting it into Python for a quick analysis script.

The real payload shape

Trimmed to one entry, this is what a leaderboard row looks like coming out of the API (values replaced, structure untouched):

{
  "ranking": [
    {
      "username": "hunter_884",
      "level": 27,
      "xp": 15420,
      "total_workouts": 63,
      "effort_score": 812.5,
      "hunter_class": "assassin",
      "equipped_title": "title_dawnbreaker",
      "equipped_theme": "theme_violet",
      "equipped_weapon": null
    }
  ],
  "mode": "global"
}

The first thing that breaks a naive conversion

Paste that straight into a Python dict and two things need attention. First, null becomes None — fine on its own, but if downstream code does row["equipped_weapon"].upper() without checking for None first, it throws. Second, effort_score is a float that came from a MySQL computed column; formatting it for display without rounding shows ugly values like 812.5000000001 in some rows, which is a classic floating-point artifact from aggregation, not a JSON conversion issue — worth knowing the difference when debugging.

import json

data = json.loads(payload)
for row in data["ranking"]:
    weapon = row["equipped_weapon"] or "none equipped"
    score = round(row["effort_score"], 1)
    print(f'{row["username"]}: level {row["level"]}, {score} pts, {weapon}')

Why this API almost went down entirely

The app was hosted on a free PHP host while I validated the idea. Its anti-bot layer started intercepting the app's own API calls — not malicious traffic, just the app's normal JSON requests — and returning an HTML challenge page instead of JSON. json.loads() (and the app's own JS fetch) failed on that HTML with a parse error, which is a good reminder: a "JSON decode error" in production is very often not bad JSON at all, it is something upstream — a proxy, a WAF, an expired auth layer — returning HTML or an error page where JSON was expected. The fix was not in the parsing code, it was migrating off a host whose bot protection could not distinguish the app's own client from an attacker.

Debugging tip: if a JSON parse error appears in production but the payload looked fine in testing, check the raw response body before touching the parsing code — you may be looking at an HTML error page, not malformed JSON.

Next steps

Paste your own API response into the JSON to Python tool to check its shape before writing conversion code, or use the JSON Formatter to inspect a payload that failed to parse.