[
  {
    "path": ".eslintrc.cjs",
    "content": "module.exports = {\n  root: true,\n  env: { browser: true, es2020: true },\n  extends: [\n    'standard',\n    'eslint:recommended',\n    'plugin:react/recommended',\n    'plugin:@typescript-eslint/recommended',\n    'plugin:react-hooks/recommended',\n    'prettier',\n  ],\n  ignorePatterns: ['node_modules', 'dist', 'htmlcov'],\n  parser: '@typescript-eslint/parser',\n  plugins: ['react', '@typescript-eslint', 'react-refresh', 'simple-import-sort'],\n  rules: {\n    'react-refresh/only-export-components': 'off', // how much effect does this have?\n    '@typescript-eslint/no-explicit-any': 'off',\n    'no-use-before-define': 'off',\n    'react/react-in-jsx-scope': 'off',\n    'react/prop-types': 'off',\n    'react/display-name': 'off',\n    'import/order': [\n      'error',\n      {\n        'newlines-between': 'always',\n        groups: ['builtin', 'external', 'internal', 'object', 'type', 'parent', 'index', 'sibling'],\n        pathGroups: [\n          {\n            pattern: '@/**',\n            group: 'internal',\n          },\n          {\n            pattern: './../**',\n            group: 'parent',\n          },\n        ],\n      },\n    ],\n  },\n}\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# Keep GitHub Actions up to date with GitHub's Dependabot...\n# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot\n# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem\nversion: 2\nupdates:\n  - package-ecosystem: github-actions\n    directory: /\n    groups:\n      github-actions:\n        patterns:\n          - \"*\"  # Group all Actions updates into a single larger pull request\n    schedule:\n      interval: monthly\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    branches:\n      - main\n    tags:\n      - '**'\n  pull_request:\n    types: [opened, synchronize]\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: actions/setup-python@v5\n        with:\n          python-version: '3.11'\n\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 18\n\n      - run: pip install -r src/python-fastui/requirements/all.txt\n      - run: pip install src/python-fastui\n\n      - run: npm install\n\n      - uses: pre-commit/action@v3.0.1\n        with:\n          extra_args: --all-files\n        env:\n          SKIP: no-commit-to-branch\n\n  docs-build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: actions/setup-python@v5\n        with:\n          python-version: '3.11'\n\n      # note: PPPR_TOKEN is not available on PRs sourced from forks, but the necessary\n      # dependencies are also listed in docs.txt :)\n      - name: install\n        run: |\n          pip install --upgrade pip\n          pip install --extra-index-url https://pydantic:${PPPR_TOKEN}@pppr.pydantic.dev/simple/ mkdocs-material mkdocstrings-python\n          pip install -r requirements/docs.txt\n        # note -- we can use these in the future when mkdocstrings-typescript and griffe-typedoc beocome publicly available\n        # pip install --extra-index-url https://pydantic:${PPPR_TOKEN}@pppr.pydantic.dev/simple/ mkdocs-material mkdocstrings-python griffe-typedoc mkdocstrings-typescript\n        # npm install\n        # npm install -g typedoc\n        env:\n          PPPR_TOKEN: ${{ secrets.PPPR_TOKEN }}\n\n      - name: build site\n        run: mkdocs build --strict\n\n  test:\n    name: test ${{ matrix.python-version }} on ${{ matrix.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest, macos-15-intel, macos-latest]\n        python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']\n        exclude:\n          - os: macos-15-intel\n            python-version: '3.10'\n          - os: macos-15-intel\n            python-version: '3.11'\n          - os: macos-15-intel\n            python-version: '3.12'\n          - os: macos-latest\n            python-version: '3.13'\n\n    runs-on: ${{ matrix.os }}\n\n    env:\n      PYTHON: ${{ matrix.python-version }}\n      OS: ${{ matrix.os }}\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: set up python\n        uses: actions/setup-python@v5\n        with:\n          python-version: ${{ matrix.python-version }}\n\n      - run: pip install -r src/python-fastui/requirements/test.txt\n      - run: pip install -r src/python-fastui/requirements/pyproject.txt\n      - run: pip install -e src/python-fastui\n\n      - run: coverage run -m pytest src\n      # display coverage and fail if it's below 80%, which shouldn't happen\n      - run: coverage report --fail-under=80\n\n      # test demo on 3.11 and 3.12, these tests are intentionally omitted from coverage\n      - if: matrix.python-version == '3.11' || matrix.python-version == '3.12'\n        run: pytest demo/tests.py\n\n      - run: coverage xml\n\n      - uses: codecov/codecov-action@v5\n        with:\n          file: ./coverage.xml\n          env_vars: PYTHON,OS\n\n  npm-build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 18\n\n      - run: npm install\n      - run: npm run build\n      - run: tree src\n\n  check: # This job does nothing and is only used for the branch protection\n    if: always()\n    needs: [lint, test, npm-build]\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Decide whether the needed jobs succeeded or failed\n        uses: re-actors/alls-green@release/v1\n        id: all-green\n        with:\n          jobs: ${{ toJSON(needs) }}\n\n  release:\n    needs: [check]\n    if: \"success() && startsWith(github.ref, 'refs/tags/')\"\n    runs-on: ubuntu-latest\n    environment: release\n\n    permissions:\n      id-token: write\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: actions/setup-python@v5\n        with:\n          python-version: '3.11'\n\n      - run: pip install -U build\n\n      - id: check-version\n        uses: samuelcolvin/check-python-version@v4.1\n        with:\n          version_file_path: 'src/python-fastui/fastui/__init__.py'\n\n      - run: python -m build --outdir dist src/python-fastui\n\n      - run: ls -lh dist\n\n      - uses: pypa/gh-action-pypi-publish@release/v1\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n/**/*.egg-info\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n\n# python\n/env*/\n__pycache__/\n\n/.logfire/\n/frontend-dist/\n/scratch/\n/packages-dist/\n/.coverage\n/users.db\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "repos:\n  - repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v5.0.0\n    hooks:\n      - id: no-commit-to-branch\n      - id: check-yaml\n        args: ['--unsafe']\n      - id: check-toml\n      - id: end-of-file-fixer\n      - id: trailing-whitespace\n\n  - repo: local\n    hooks:\n      - id: python-format\n        name: python-format\n        types_or: [python]\n        entry: make format\n        language: system\n        pass_filenames: false\n      - id: python-typecheck\n        name: python-typecheck\n        types_or: [python]\n        entry: make typecheck\n        language: system\n        pass_filenames: false\n      - id: js-prettier\n        name: js-prettier\n        types_or: [javascript, jsx, ts, tsx, css, json, markdown]\n        entry: npm run prettier\n        language: system\n        exclude: '^docs/.*'\n      - id: js-lint\n        name: js-lint\n        types_or: [ts, tsx]\n        entry: npm run lint-fix\n        language: system\n        pass_filenames: false\n      - id: js-typecheck\n        name: js-typecheck\n        types_or: [ts, tsx]\n        entry: npm run typecheck\n        language: system\n        pass_filenames: false\n      - id: python-generate-ts\n        name: python-generate-ts\n        types_or: [python]\n        entry: make typescript-models\n        language: system\n        pass_filenames: false\n"
  },
  {
    "path": ".prettierignore",
    "content": "htmlcov/\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2023 to present Pydantic Services inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": ".DEFAULT_GOAL:=all\npath = src/python-fastui\n\n.PHONY: install\ninstall:\n\tpip install -U pip pre-commit pip-tools\n\tpip install -r $(path)/requirements/all.txt\n\tpip install -e $(path)\n\tpre-commit install\n\n\n.PHONY: install-docs\ninstall-docs:\n\tpip install -r requirements/docs.txt\n\n# note -- mkdocstrings-typescript and griffe-typedoc are not yet publicly available\n# but the following can be added above the pip install -r requirements/docs.txt line in the future\n# pip install mkdocstrings-python mkdocstrings-typescript griffe-typedoc\n\n.PHONY: update-lockfiles\nupdate-lockfiles:\n\t@echo \"Updating requirements files using pip-compile\"\n\tpip-compile -q --strip-extras -o $(path)/requirements/lint.txt $(path)/requirements/lint.in\n\tpip-compile -q --strip-extras -o $(path)/requirements/pyproject.txt -c $(path)/requirements/lint.txt $(path)/pyproject.toml --extra=fastapi\n\tpip-compile -q --strip-extras -o $(path)/requirements/test.txt -c $(path)/requirements/lint.txt -c $(path)/requirements/pyproject.txt $(path)/requirements/test.in\n\tpip install --dry-run -r $(path)/requirements/all.txt\n\n.PHONY: format\nformat:\n\truff check --fix-only $(path) demo\n\truff format $(path) demo\n\n.PHONY: lint\nlint:\n\truff check $(path) demo\n\truff format --check $(path) demo\n\n.PHONY: typecheck\ntypecheck:\n\tpyright\n\n.PHONY: test\ntest:\n\tcoverage run -m pytest\n\n.PHONY: testcov\ntestcov: test\n\tcoverage html\n\n.PHONY: typescript-models\ntypescript-models:\n\tfastui generate fastui:FastUI src/npm-fastui/src/models.d.ts\n\n.PHONY: dev\ndev:\n\tuvicorn demo:app --reload --reload-dir .\n\n.PHONY: docs\ndocs:\n\tmkdocs build\n\n.PHONY: serve\nserve:\n\tmkdocs serve\n\n.PHONY: all\nall: testcov lint\n"
  },
  {
    "path": "README.md",
    "content": "# NOTE: this project is inactive, see [#368](https://github.com/pydantic/FastUI/issues/368)\n\n# FastUI\n\nFind the documentation [here](https://docs.pydantic.dev/fastui/).\nJoin the discussion in the #fastui slack channel [here](https://pydanticlogfire.slack.com/archives/C0720M7D31S)\n\n[![CI](https://github.com/pydantic/FastUI/actions/workflows/ci.yml/badge.svg)](https://github.com/pydantic/FastUI/actions?query=event%3Apush+branch%3Amain+workflow%3ACI)\n[![pypi](https://img.shields.io/pypi/v/fastui.svg)](https://pypi.python.org/pypi/fastui)\n[![versions](https://img.shields.io/pypi/pyversions/fastui.svg)](https://github.com/pydantic/FastUI)\n[![license](https://img.shields.io/github/license/pydantic/FastUI.svg)](https://github.com/pydantic/FastUI/blob/main/LICENSE)\n\n**Please note:** FastUI is still an active work in progress, do not expect it to be complete.\n\n## The Principle (short version)\n\nYou can see a simple demo of an application built with FastUI [here](https://fastui-demo.onrender.com).\n\nFastUI is a new way to build web application user interfaces defined by declarative Python code.\n\nThis means:\n\n- **If you're a Python developer** — you can build responsive web applications using React without writing a single line of JavaScript, or touching `npm`.\n- **If you're a frontend developer** — you can concentrate on building magical components that are truly reusable, no copy-pasting components for each view.\n- **For everyone** — a true separation of concerns, the backend defines the entire application; while the frontend is free to implement just the user interface\n\nAt its heart, FastUI is a set of matching [Pydantic](https://docs.pydantic.dev) models and TypeScript interfaces that allow you to define a user interface. This interface is validated at build time by TypeScript and pyright/mypy and at runtime by Pydantic.\n\n## The Practice — Usage\n\nFastUI is made up of 4 things:\n\n- [`fastui` PyPI package](https://pypi.python.org/pypi/fastui) — Pydantic models for UI components, and some utilities. While it works well with [FastAPI](https://fastapi.tiangolo.com) it doesn't depend on FastAPI, and most of it could be used with any python web framework.\n- [`@pydantic/fastui` npm package](https://www.npmjs.com/package/@pydantic/fastui) — a React TypeScript package that lets you reuse the machinery and types of FastUI while implementing your own components\n- [`@pydantic/fastui-bootstrap` npm package](https://www.npmjs.com/package/@pydantic/fastui-bootstrap) — implementation/customisation of all FastUI components using [Bootstrap](https://getbootstrap.com)\n- [`@pydantic/fastui-prebuilt` npm package](https://www.jsdelivr.com/package/npm/@pydantic/fastui-prebuilt) (available on [jsdelivr.com CDN](https://www.jsdelivr.com/package/npm/@pydantic/fastui-prebuilt)) providing a pre-built version of the FastUI React app so you can use it without installing any npm packages or building anything yourself. The Python package provides a simple HTML page to serve this app.\n\nHere's a simple but complete FastAPI application that uses FastUI to show some user profiles:\n\n```python\nfrom datetime import date\n\nfrom fastapi import FastAPI, HTTPException\nfrom fastapi.responses import HTMLResponse\nfrom fastui import FastUI, AnyComponent, prebuilt_html, components as c\nfrom fastui.components.display import DisplayMode, DisplayLookup\nfrom fastui.events import GoToEvent, BackEvent\nfrom pydantic import BaseModel, Field\n\napp = FastAPI()\n\n\nclass User(BaseModel):\n    id: int\n    name: str\n    dob: date = Field(title='Date of Birth')\n\n\n# define some users\nusers = [\n    User(id=1, name='John', dob=date(1990, 1, 1)),\n    User(id=2, name='Jack', dob=date(1991, 1, 1)),\n    User(id=3, name='Jill', dob=date(1992, 1, 1)),\n    User(id=4, name='Jane', dob=date(1993, 1, 1)),\n]\n\n\n@app.get(\"/api/\", response_model=FastUI, response_model_exclude_none=True)\ndef users_table() -> list[AnyComponent]:\n    \"\"\"\n    Show a table of four users, `/api` is the endpoint the frontend will connect to\n    when a user visits `/` to fetch components to render.\n    \"\"\"\n    return [\n        c.Page(  # Page provides a basic container for components\n            components=[\n                c.Heading(text='Users', level=2),  # renders `<h2>Users</h2>`\n                c.Table(\n                    data=users,\n                    # define two columns for the table\n                    columns=[\n                        # the first is the users, name rendered as a link to their profile\n                        DisplayLookup(field='name', on_click=GoToEvent(url='/user/{id}/')),\n                        # the second is the date of birth, rendered as a date\n                        DisplayLookup(field='dob', mode=DisplayMode.date),\n                    ],\n                ),\n            ]\n        ),\n    ]\n\n\n@app.get(\"/api/user/{user_id}/\", response_model=FastUI, response_model_exclude_none=True)\ndef user_profile(user_id: int) -> list[AnyComponent]:\n    \"\"\"\n    User profile page, the frontend will fetch this when the user visits `/user/{id}/`.\n    \"\"\"\n    try:\n        user = next(u for u in users if u.id == user_id)\n    except StopIteration:\n        raise HTTPException(status_code=404, detail=\"User not found\")\n    return [\n        c.Page(\n            components=[\n                c.Heading(text=user.name, level=2),\n                c.Link(components=[c.Text(text='Back')], on_click=BackEvent()),\n                c.Details(data=user),\n            ]\n        ),\n    ]\n\n\n@app.get('/{path:path}')\nasync def html_landing() -> HTMLResponse:\n    \"\"\"Simple HTML page which serves the React app, comes last as it matches all paths.\"\"\"\n    return HTMLResponse(prebuilt_html(title='FastUI Demo'))\n```\n\nWhich renders like this:\n\n![screenshot](https://raw.githubusercontent.com/pydantic/FastUI/main/screenshot.png)\n\nOf course, that's a very simple application, the [full demo](https://fastui-demo.onrender.com) is more complete.\n\n### Components\n\nFastUI already defines a rich set of components.\n\nAll components are listed in the [demo app](https://fastui-demo.onrender.com).\n\n## The Principle (long version)\n\nFastUI is an implementation of the RESTful principle; but not as it's usually understood, instead I mean the principle defined in the original [PhD dissertation](https://ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) by Roy Fielding, and excellently summarised in [this essay on htmx.org](https://htmx.org/essays/how-did-rest-come-to-mean-the-opposite-of-rest/) (HTMX people, I'm sorry to use your article to promote React which I know you despise 🙏).\n\nThe RESTful principle as described in the HTMX article is that the frontend doesn't need to (and shouldn't) know anything about the application you're building. Instead, it should just provide all the components you need to construct the interface, the backend can then tell the frontend what to do.\n\nThink of your frontend as a puppet, and the backend as the hand within it — the puppet doesn't need to know what to say, that's kind of the point.\n\nBuilding an application this way has a number of significant advantages:\n\n- You only need to write code in one place to build a new feature — add a new view, change the behavior of an existing view or alter the URL structure\n- Deploying the front and backend can be completely decoupled, provided the frontend knows how to render all the components the backend is going to ask it to use, you're good to go\n- You should be able to reuse a rich set of opensource components, they should end up being better tested and more reliable than anything you could build yourself, this is possible because the components need no context about how they're going to be used (note: since FastUI is brand new, this isn't true yet, hopefully we get there)\n- We can use Pydantic, TypeScript and JSON Schema to provide guarantees that the two sides are communicating with an agreed schema\n\nIn the abstract, FastUI is like the opposite of GraphQL but with the same goal — GraphQL lets frontend developers extend an application without any new backend development; FastUI lets backend developers extend an application without any new frontend development.\n\n### Beyond Python and React\n\nOf course, this principle shouldn't be limited to Python and React applications — provided we use the same set of agreed schemas and encoding to communicate, we should be able to use any frontend and backend that implements the schema. Interchangeably.\n\nThis could mean:\n\n- Implementing a web frontend using another JS framework like Vue — lots of work, limited value IMHO\n- Implementing a web frontend using an edge server, so the browser just sees HTML — lots of work but very valuable\n- Implementing frontends for other platforms like mobile or IOT — lots of work, no idea if it's actually a good idea?\n- Implementing the component models in another language like Rust or Go — since there's actually not that much code in the backend, so this would be a relatively small and mechanical task\n"
  },
  {
    "path": "build-docs.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\nset -x\n\npython3 -V\n\npython3 -m pip install --extra-index-url https://pydantic:${PPPR_TOKEN}@pppr.pydantic.dev/simple/ mkdocs-material mkdocstrings-python\npython3 -m pip install -r ./requirements/docs.txt\n# note -- we can use these in the future when mkdocstrings-typescript and griffe-typedoc beocome publicly available\n# python3 -m pip install --extra-index-url https://pydantic:$PPPR_TOKEN@pppr.pydantic.dev/simple/ mkdocs-material mkdocstrings-python griffe-typedoc mkdocstrings-typescript\n# npm install\n# npm install -g typedoc\n\npython3 -m mkdocs build\n"
  },
  {
    "path": "bump_npm.py",
    "content": "#!/usr/bin/env python\nfrom __future__ import annotations\n\nimport json\nimport re\nfrom pathlib import Path\n\n\ndef replace_package_json(package_json: Path, new_version: str, deps: bool = False) -> tuple[Path, str]:\n    content = package_json.read_text()\n    content, r_count = re.subn(r'\"version\": *\".*?\"', f'\"version\": \"{new_version}\"', content, count=1)\n    assert r_count == 1 , f'Failed to update version in {package_json}, expect replacement count 1, got {r_count}'\n    if deps:\n        content, r_count = re.subn(r'\"(@pydantic/.+?)\": *\".*?\"', fr'\"\\1\": \"{new_version}\"', content)\n        assert r_count == 1, f'Failed to update version in {package_json}, expect replacement count 1, got {r_count}'\n\n    return package_json, content\n\n\ndef main():\n    this_dir = Path(__file__).parent\n    fastui_package_json = this_dir / 'src/npm-fastui/package.json'\n    with fastui_package_json.open() as f:\n        old_version = json.load(f)['version']\n\n    rest, patch_version = old_version.rsplit('.', 1)\n    new_version = f'{rest}.{int(patch_version) + 1}'\n    bootstrap_package_json = this_dir / 'src/npm-fastui-bootstrap/package.json'\n    prebuilt_package_json = this_dir / 'src/npm-fastui-prebuilt/package.json'\n    to_update: list[tuple[Path, str]] = [\n        replace_package_json(fastui_package_json, new_version),\n        replace_package_json(bootstrap_package_json, new_version, deps=True),\n        replace_package_json(prebuilt_package_json, new_version),\n    ]\n\n    python_init = this_dir / 'src/python-fastui/fastui/__init__.py'\n    python_content = python_init.read_text()\n    python_content, r_count = re.subn(r\"(_PREBUILT_VERSION = )'.+'\", fr\"\\1'{new_version}'\", python_content)\n    assert r_count == 1, f'Failed to update version in {python_init}, expect replacement count 1, got {r_count}'\n    to_update.append((python_init, python_content))\n\n    # logic is finished, no update all files\n    print(f'Updating files:')\n    for package_json, content in to_update:\n        print(f'  {package_json.relative_to(this_dir)}')\n        package_json.write_text(content)\n\n    print(f\"\"\"\nBumped from `{old_version}` to `{new_version}` in {len(to_update)} files.\n\nTo publish the new version, run:\n\n> npm --workspaces publish\n\"\"\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "demo/README.md",
    "content": "# FastUI Demo\n\nThis a simple demo app for FastUI, it's deployed at [fastui-demo.onrender.com](https://fastui-demo.onrender.com).\n\n## Running\n\nTo run the demo app, execute the following commands from the FastUI repo root\n\n```bash\n# create a virtual env\npython3.11 -m venv env311\n# activate the env\n. env311/bin/activate\n# install deps\nmake install\n# run the demo server\nmake dev\n```\n\nThen navigate to [http://localhost:8000](http://localhost:8000)\n\nIf you want to run the dev version of the React frontend, run\n\n```bash\nnpm install\nnpm run dev\n```\n\nThis will run at [http://localhost:3000](http://localhost:3000), and connect to the backend running at `localhost:3000`.\n"
  },
  {
    "path": "demo/__init__.py",
    "content": "from __future__ import annotations as _annotations\n\nimport sys\nfrom contextlib import asynccontextmanager\n\nfrom fastapi import FastAPI\nfrom fastapi.responses import HTMLResponse, PlainTextResponse\nfrom fastui import prebuilt_html\nfrom fastui.auth import fastapi_auth_exception_handling\nfrom fastui.dev import dev_fastapi_app\nfrom httpx import AsyncClient\n\nfrom .auth import router as auth_router\nfrom .components_list import router as components_router\nfrom .forms import router as forms_router\nfrom .main import router as main_router\nfrom .sse import router as sse_router\nfrom .tables import router as table_router\n\n\n@asynccontextmanager\nasync def lifespan(app_: FastAPI):\n    async with AsyncClient() as client:\n        app_.state.httpx_client = client\n        yield\n\n\nfrontend_reload = '--reload' in sys.argv\nif frontend_reload:\n    # dev_fastapi_app reloads in the browser when the Python source changes\n    app = dev_fastapi_app(lifespan=lifespan)\nelse:\n    app = FastAPI(lifespan=lifespan)\n\nfastapi_auth_exception_handling(app)\napp.include_router(components_router, prefix='/api/components')\napp.include_router(sse_router, prefix='/api/components')\napp.include_router(table_router, prefix='/api/table')\napp.include_router(forms_router, prefix='/api/forms')\napp.include_router(auth_router, prefix='/api/auth')\napp.include_router(main_router, prefix='/api')\n\n\n@app.get('/robots.txt', response_class=PlainTextResponse)\nasync def robots_txt() -> str:\n    return 'User-agent: *\\nAllow: /'\n\n\n@app.get('/favicon.ico', status_code=404, response_class=PlainTextResponse)\nasync def favicon_ico() -> str:\n    return 'page not found'\n\n\n@app.get('/{path:path}')\nasync def html_landing() -> HTMLResponse:\n    return HTMLResponse(prebuilt_html(title='FastUI Demo'))\n"
  },
  {
    "path": "demo/auth.py",
    "content": "from __future__ import annotations as _annotations\n\nimport asyncio\nimport json\nimport os\nfrom dataclasses import asdict\nfrom typing import Annotated, Literal, TypeAlias\n\nfrom fastapi import APIRouter, Depends, Request\nfrom fastui import AnyComponent, FastUI\nfrom fastui import components as c\nfrom fastui.auth import AuthRedirect, GitHubAuthProvider\nfrom fastui.events import AuthEvent, GoToEvent, PageEvent\nfrom fastui.forms import fastui_form\nfrom httpx import AsyncClient\nfrom pydantic import BaseModel, EmailStr, Field, SecretStr\n\nfrom .auth_user import User\nfrom .shared import demo_page\n\nrouter = APIRouter()\n\nGITHUB_CLIENT_ID = os.getenv('GITHUB_CLIENT_ID', '0d0315f9c2e055d032e2')\n# this will give an error when making requests to GitHub, but at least the app will run\nGITHUB_CLIENT_SECRET = SecretStr(os.getenv('GITHUB_CLIENT_SECRET', 'dummy-secret'))\n# use 'http://localhost:3000/auth/login/github/redirect' in development\nGITHUB_REDIRECT = os.getenv('GITHUB_REDIRECT')\n\n\nasync def get_github_auth(request: Request) -> GitHubAuthProvider:\n    client: AsyncClient = request.app.state.httpx_client\n    return GitHubAuthProvider(\n        httpx_client=client,\n        github_client_id=GITHUB_CLIENT_ID,\n        github_client_secret=GITHUB_CLIENT_SECRET,\n        redirect_uri=GITHUB_REDIRECT,\n        scopes=['user:email'],\n    )\n\n\nLoginKind: TypeAlias = Literal['password', 'github']\n\n\n@router.get('/login/{kind}', response_model=FastUI, response_model_exclude_none=True)\ndef auth_login(\n    kind: LoginKind,\n    user: Annotated[User | None, Depends(User.from_request_opt)],\n) -> list[AnyComponent]:\n    if user is not None:\n        # already logged in\n        raise AuthRedirect('/auth/profile')\n\n    return demo_page(\n        c.LinkList(\n            links=[\n                c.Link(\n                    components=[c.Text(text='Password Login')],\n                    on_click=PageEvent(name='tab', push_path='/auth/login/password', context={'kind': 'password'}),\n                    active='/auth/login/password',\n                ),\n                c.Link(\n                    components=[c.Text(text='GitHub Login')],\n                    on_click=PageEvent(name='tab', push_path='/auth/login/github', context={'kind': 'github'}),\n                    active='/auth/login/github',\n                ),\n            ],\n            mode='tabs',\n            class_name='+ mb-4',\n        ),\n        c.ServerLoad(\n            path='/auth/login/content/{kind}',\n            load_trigger=PageEvent(name='tab'),\n            components=auth_login_content(kind),\n        ),\n        title='Authentication',\n    )\n\n\n@router.get('/login/content/{kind}', response_model=FastUI, response_model_exclude_none=True)\ndef auth_login_content(kind: LoginKind) -> list[AnyComponent]:\n    match kind:\n        case 'password':\n            return [\n                c.Heading(text='Password Login', level=3),\n                c.Paragraph(\n                    text=(\n                        'This is a very simple demo of password authentication, '\n                        'here you can \"login\" with any email address and password.'\n                    )\n                ),\n                c.Paragraph(text='(Passwords are not saved and is email stored in the browser via a JWT only)'),\n                c.ModelForm(model=LoginForm, submit_url='/api/auth/login', display_mode='page'),\n            ]\n        case 'github':\n            return [\n                c.Heading(text='GitHub Login', level=3),\n                c.Paragraph(text='Demo of GitHub authentication.'),\n                c.Paragraph(text='(Credentials are stored in the browser via a JWT only)'),\n                c.Button(text='Login with GitHub', on_click=GoToEvent(url='/auth/login/github/gen')),\n            ]\n        case _:\n            raise ValueError(f'Invalid kind {kind!r}')\n\n\nclass LoginForm(BaseModel):\n    email: EmailStr = Field(\n        title='Email Address', description='Enter whatever value you like', json_schema_extra={'autocomplete': 'email'}\n    )\n    password: SecretStr = Field(\n        title='Password',\n        description='Enter whatever value you like, password is not checked',\n        json_schema_extra={'autocomplete': 'current-password'},\n    )\n\n\n@router.post('/login', response_model=FastUI, response_model_exclude_none=True)\nasync def login_form_post(form: Annotated[LoginForm, fastui_form(LoginForm)]) -> list[AnyComponent]:\n    user = User(email=form.email, extra={})\n    token = user.encode_token()\n    return [c.FireEvent(event=AuthEvent(token=token, url='/auth/profile'))]\n\n\n@router.get('/profile', response_model=FastUI, response_model_exclude_none=True)\nasync def profile(user: Annotated[User, Depends(User.from_request)]) -> list[AnyComponent]:\n    return demo_page(\n        c.Paragraph(text=f'You are logged in as \"{user.email}\".'),\n        c.Button(text='Logout', on_click=PageEvent(name='submit-form')),\n        c.Heading(text='User Data:', level=3),\n        c.Code(language='json', text=json.dumps(asdict(user), indent=2)),\n        c.Form(\n            submit_url='/api/auth/logout',\n            form_fields=[c.FormFieldInput(name='test', title='', initial='data', html_type='hidden')],\n            footer=[],\n            submit_trigger=PageEvent(name='submit-form'),\n        ),\n        title='Authentication',\n    )\n\n\n@router.post('/logout', response_model=FastUI, response_model_exclude_none=True)\nasync def logout_form_post() -> list[AnyComponent]:\n    return [c.FireEvent(event=AuthEvent(token=False, url='/auth/login/password'))]\n\n\n@router.get('/login/github/gen', response_model=FastUI, response_model_exclude_none=True)\nasync def auth_github_gen(github_auth: Annotated[GitHubAuthProvider, Depends(get_github_auth)]) -> list[AnyComponent]:\n    auth_url = await github_auth.authorization_url()\n    return [c.FireEvent(event=GoToEvent(url=auth_url))]\n\n\n@router.get('/login/github/redirect', response_model=FastUI, response_model_exclude_none=True)\nasync def github_redirect(\n    code: str,\n    state: str | None,\n    github_auth: Annotated[GitHubAuthProvider, Depends(get_github_auth)],\n) -> list[AnyComponent]:\n    exchange = await github_auth.exchange_code(code, state)\n    user_info, emails = await asyncio.gather(\n        github_auth.get_github_user(exchange), github_auth.get_github_user_emails(exchange)\n    )\n    user = User(\n        email=next((e.email for e in emails if e.primary and e.verified), None),\n        extra={\n            'github_user_info': user_info.model_dump(),\n            'github_emails': [e.model_dump() for e in emails],\n        },\n    )\n    token = user.encode_token()\n    return [c.FireEvent(event=AuthEvent(token=token, url='/auth/profile'))]\n"
  },
  {
    "path": "demo/auth_user.py",
    "content": "import json\nfrom dataclasses import asdict, dataclass\nfrom datetime import datetime, timedelta\nfrom typing import Annotated, Any\n\nimport jwt\nfrom fastapi import Header, HTTPException\nfrom fastui.auth import AuthRedirect\nfrom typing_extensions import Self\n\nJWT_SECRET = 'secret'\n\n\n@dataclass\nclass User:\n    email: str | None\n    extra: dict[str, Any]\n\n    def encode_token(self) -> str:\n        payload = asdict(self)\n        payload['exp'] = datetime.now() + timedelta(hours=1)\n        return jwt.encode(payload, JWT_SECRET, algorithm='HS256', json_encoder=CustomJsonEncoder)\n\n    @classmethod\n    def from_request(cls, authorization: Annotated[str, Header()] = '') -> Self:\n        user = cls.from_request_opt(authorization)\n        if user is None:\n            raise AuthRedirect('/auth/login/password')\n        else:\n            return user\n\n    @classmethod\n    def from_request_opt(cls, authorization: Annotated[str, Header()] = '') -> Self | None:\n        try:\n            token = authorization.split(' ', 1)[1]\n        except IndexError:\n            return None\n\n        try:\n            payload = jwt.decode(token, JWT_SECRET, algorithms=['HS256'])\n        except jwt.ExpiredSignatureError:\n            return None\n        except jwt.DecodeError:\n            raise HTTPException(status_code=401, detail='Invalid token')\n        else:\n            # existing token might not have 'exp' field\n            payload.pop('exp', None)\n            return cls(**payload)\n\n\nclass CustomJsonEncoder(json.JSONEncoder):\n    def default(self, obj: Any) -> Any:\n        if isinstance(obj, datetime):\n            return obj.isoformat()\n        else:\n            return super().default(obj)\n"
  },
  {
    "path": "demo/cities.json",
    "content": "[\n  {\n    \"city\": \"Kandahār\",\n    \"city_ascii\": \"Kandahar\",\n    \"lat\": 31.62,\n    \"lng\": 65.7158,\n    \"country\": \"Afghanistan\",\n    \"iso2\": \"AF\",\n    \"iso3\": \"AFG\",\n    \"admin_name\": \"Kandahār\",\n    \"capital\": \"admin\",\n    \"population\": 614254.0,\n    \"id\": 1004003059\n  },\n  {\n    \"city\": \"Herāt\",\n    \"city_ascii\": \"Herat\",\n    \"lat\": 34.3419,\n    \"lng\": 62.2031,\n    \"country\": \"Afghanistan\",\n    \"iso2\": \"AF\",\n    \"iso3\": \"AFG\",\n    \"admin_name\": \"Herāt\",\n    \"capital\": \"admin\",\n    \"population\": 556205.0,\n    \"id\": 1004237782\n  },\n  {\n    \"city\": \"Mazār-e Sharīf\",\n    \"city_ascii\": \"Mazar-e Sharif\",\n    \"lat\": 36.7,\n    \"lng\": 67.1167,\n    \"country\": \"Afghanistan\",\n    \"iso2\": \"AF\",\n    \"iso3\": \"AFG\",\n    \"admin_name\": \"Balkh\",\n    \"capital\": \"admin\",\n    \"population\": 469247.0,\n    \"id\": 1004436363\n  },\n  {\n    \"city\": \"Farāh\",\n    \"city_ascii\": \"Farah\",\n    \"lat\": 32.3436,\n    \"lng\": 62.1194,\n    \"country\": \"Afghanistan\",\n    \"iso2\": \"AF\",\n    \"iso3\": \"AFG\",\n    \"admin_name\": \"Farāh\",\n    \"capital\": \"admin\",\n    \"population\": 500000.0,\n    \"id\": 1004523791\n  },\n  {\n    \"city\": \"Kabul\",\n    \"city_ascii\": \"Kabul\",\n    \"lat\": 34.5253,\n    \"lng\": 69.1783,\n    \"country\": \"Afghanistan\",\n    \"iso2\": \"AF\",\n    \"iso3\": \"AFG\",\n    \"admin_name\": \"Kābul\",\n    \"capital\": \"primary\",\n    \"population\": 4273156.0,\n    \"id\": 1004993580\n  },\n  {\n    \"city\": \"Tirana\",\n    \"city_ascii\": \"Tirana\",\n    \"lat\": 41.3289,\n    \"lng\": 19.8178,\n    \"country\": \"Albania\",\n    \"iso2\": \"AL\",\n    \"iso3\": \"ALB\",\n    \"admin_name\": \"Tiranë\",\n    \"capital\": \"primary\",\n    \"population\": 418495.0,\n    \"id\": 1008162156\n  },\n  {\n    \"city\": \"Oran\",\n    \"city_ascii\": \"Oran\",\n    \"lat\": 35.6969,\n    \"lng\": -0.6331,\n    \"country\": \"Algeria\",\n    \"iso2\": \"DZ\",\n    \"iso3\": \"DZA\",\n    \"admin_name\": \"Oran\",\n    \"capital\": \"admin\",\n    \"population\": 852000.0,\n    \"id\": 1012126319\n  },\n  {\n    \"city\": \"Constantine\",\n    \"city_ascii\": \"Constantine\",\n    \"lat\": 36.365,\n    \"lng\": 6.6147,\n    \"country\": \"Algeria\",\n    \"iso2\": \"DZ\",\n    \"iso3\": \"DZA\",\n    \"admin_name\": \"Constantine\",\n    \"capital\": \"admin\",\n    \"population\": 448374.0,\n    \"id\": 1012275076\n  },\n  {\n    \"city\": \"Algiers\",\n    \"city_ascii\": \"Algiers\",\n    \"lat\": 36.7539,\n    \"lng\": 3.0589,\n    \"country\": \"Algeria\",\n    \"iso2\": \"DZ\",\n    \"iso3\": \"DZA\",\n    \"admin_name\": \"Alger\",\n    \"capital\": \"primary\",\n    \"population\": 3415811.0,\n    \"id\": 1012973369\n  },\n  {\n    \"city\": \"Huambo\",\n    \"city_ascii\": \"Huambo\",\n    \"lat\": -12.7767,\n    \"lng\": 15.7347,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Huambo\",\n    \"capital\": \"admin\",\n    \"population\": 665564.0,\n    \"id\": 1024079828\n  },\n  {\n    \"city\": \"Lobito\",\n    \"city_ascii\": \"Lobito\",\n    \"lat\": -12.3597,\n    \"lng\": 13.5308,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Benguela\",\n    \"capital\": null,\n    \"population\": 393079.0,\n    \"id\": 1024128946\n  },\n  {\n    \"city\": \"Benguela\",\n    \"city_ascii\": \"Benguela\",\n    \"lat\": -12.55,\n    \"lng\": 13.4167,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Benguela\",\n    \"capital\": \"admin\",\n    \"population\": 561775.0,\n    \"id\": 1024141961\n  },\n  {\n    \"city\": \"Belas\",\n    \"city_ascii\": \"Belas\",\n    \"lat\": -8.9983,\n    \"lng\": 13.265,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Luanda\",\n    \"capital\": null,\n    \"population\": 500000.0,\n    \"id\": 1024196826\n  },\n  {\n    \"city\": \"Luena\",\n    \"city_ascii\": \"Luena\",\n    \"lat\": -11.7918,\n    \"lng\": 19.9062,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Moxico\",\n    \"capital\": \"admin\",\n    \"population\": 357413.0,\n    \"id\": 1024283760\n  },\n  {\n    \"city\": \"Saurimo\",\n    \"city_ascii\": \"Saurimo\",\n    \"lat\": -9.65,\n    \"lng\": 20.4,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Lunda-Sul\",\n    \"capital\": \"admin\",\n    \"population\": 393000.0,\n    \"id\": 1024326839\n  },\n  {\n    \"city\": \"Cabinda\",\n    \"city_ascii\": \"Cabinda\",\n    \"lat\": -5.56,\n    \"lng\": 12.19,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Cabinda\",\n    \"capital\": \"admin\",\n    \"population\": 739182.0,\n    \"id\": 1024474012\n  },\n  {\n    \"city\": \"Cacuaco\",\n    \"city_ascii\": \"Cacuaco\",\n    \"lat\": -8.8053,\n    \"lng\": 13.2444,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Luanda\",\n    \"capital\": null,\n    \"population\": 1279488.0,\n    \"id\": 1024559448\n  },\n  {\n    \"city\": \"Cubal\",\n    \"city_ascii\": \"Cubal\",\n    \"lat\": -13.1117,\n    \"lng\": 14.3672,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Benguela\",\n    \"capital\": null,\n    \"population\": 357618.0,\n    \"id\": 1024580158\n  },\n  {\n    \"city\": \"Lubango\",\n    \"city_ascii\": \"Lubango\",\n    \"lat\": -14.9167,\n    \"lng\": 13.5,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Huíla\",\n    \"capital\": \"admin\",\n    \"population\": 776249.0,\n    \"id\": 1024669127\n  },\n  {\n    \"city\": \"Malanje\",\n    \"city_ascii\": \"Malanje\",\n    \"lat\": -9.5333,\n    \"lng\": 16.35,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Malanje\",\n    \"capital\": \"admin\",\n    \"population\": 604215.0,\n    \"id\": 1024774947\n  },\n  {\n    \"city\": \"Cuito\",\n    \"city_ascii\": \"Cuito\",\n    \"lat\": -12.3833,\n    \"lng\": 16.9333,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Bié\",\n    \"capital\": \"admin\",\n    \"population\": 355423.0,\n    \"id\": 1024939858\n  },\n  {\n    \"city\": \"Luanda\",\n    \"city_ascii\": \"Luanda\",\n    \"lat\": -8.8383,\n    \"lng\": 13.2344,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Luanda\",\n    \"capital\": \"primary\",\n    \"population\": 9051000.0,\n    \"id\": 1024949724\n  },\n  {\n    \"city\": \"Talatona\",\n    \"city_ascii\": \"Talatona\",\n    \"lat\": -8.9167,\n    \"lng\": 13.1833,\n    \"country\": \"Angola\",\n    \"iso2\": \"AO\",\n    \"iso3\": \"AGO\",\n    \"admin_name\": \"Luanda\",\n    \"capital\": null,\n    \"population\": 500000.0,\n    \"id\": 1024988332\n  },\n  {\n    \"city\": \"Sumqayıt\",\n    \"city_ascii\": \"Sumqayit\",\n    \"lat\": 40.5917,\n    \"lng\": 49.6397,\n    \"country\": \"Azerbaijan\",\n    \"iso2\": \"AZ\",\n    \"iso3\": \"AZE\",\n    \"admin_name\": \"Sumqayıt\",\n    \"capital\": \"admin\",\n    \"population\": 341200.0,\n    \"id\": 1031630283\n  },\n  {\n    \"city\": \"Baku\",\n    \"city_ascii\": \"Baku\",\n    \"lat\": 40.3667,\n    \"lng\": 49.8352,\n    \"country\": \"Azerbaijan\",\n    \"iso2\": \"AZ\",\n    \"iso3\": \"AZE\",\n    \"admin_name\": \"Bakı\",\n    \"capital\": \"primary\",\n    \"population\": 2300500.0,\n    \"id\": 1031946365\n  },\n  {\n    \"city\": \"Lanús\",\n    \"city_ascii\": \"Lanus\",\n    \"lat\": -34.7,\n    \"lng\": -58.4,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Buenos Aires\",\n    \"capital\": \"minor\",\n    \"population\": 459263.0,\n    \"id\": 1032009573\n  },\n  {\n    \"city\": \"Comodoro Rivadavia\",\n    \"city_ascii\": \"Comodoro Rivadavia\",\n    \"lat\": -45.8647,\n    \"lng\": -67.4808,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Chubut\",\n    \"capital\": \"minor\",\n    \"population\": 730266.0,\n    \"id\": 1032042035\n  },\n  {\n    \"city\": \"Corrientes\",\n    \"city_ascii\": \"Corrientes\",\n    \"lat\": -27.4833,\n    \"lng\": -58.8167,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Corrientes\",\n    \"capital\": \"admin\",\n    \"population\": 352646.0,\n    \"id\": 1032173097\n  },\n  {\n    \"city\": \"San Miguel de Tucumán\",\n    \"city_ascii\": \"San Miguel de Tucuman\",\n    \"lat\": -26.8167,\n    \"lng\": -65.2167,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Tucumán\",\n    \"capital\": \"admin\",\n    \"population\": 605767.0,\n    \"id\": 1032233996\n  },\n  {\n    \"city\": \"Mar del Plata\",\n    \"city_ascii\": \"Mar del Plata\",\n    \"lat\": -38.0,\n    \"lng\": -57.55,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Buenos Aires\",\n    \"capital\": \"minor\",\n    \"population\": 682605.0,\n    \"id\": 1032456103\n  },\n  {\n    \"city\": \"Santiago del Estero\",\n    \"city_ascii\": \"Santiago del Estero\",\n    \"lat\": -27.7833,\n    \"lng\": -64.2667,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Santiago del Estero\",\n    \"capital\": \"admin\",\n    \"population\": 911506.0,\n    \"id\": 1032492280\n  },\n  {\n    \"city\": \"Buenos Aires\",\n    \"city_ascii\": \"Buenos Aires\",\n    \"lat\": -34.5997,\n    \"lng\": -58.3819,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Buenos Aires, Ciudad Autónoma de\",\n    \"capital\": \"primary\",\n    \"population\": 16710000.0,\n    \"id\": 1032717330\n  },\n  {\n    \"city\": \"Florencio Varela\",\n    \"city_ascii\": \"Florencio Varela\",\n    \"lat\": -34.8167,\n    \"lng\": -58.2833,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Buenos Aires\",\n    \"capital\": null,\n    \"population\": 426005.0,\n    \"id\": 1032730758\n  },\n  {\n    \"city\": \"Rosario\",\n    \"city_ascii\": \"Rosario\",\n    \"lat\": -32.9575,\n    \"lng\": -60.6394,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Santa Fe\",\n    \"capital\": \"minor\",\n    \"population\": 1276000.0,\n    \"id\": 1032770677\n  },\n  {\n    \"city\": \"Córdoba\",\n    \"city_ascii\": \"Cordoba\",\n    \"lat\": -31.4167,\n    \"lng\": -64.1833,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Córdoba\",\n    \"capital\": \"admin\",\n    \"population\": 1565112.0,\n    \"id\": 1032803249\n  },\n  {\n    \"city\": \"Santa Fe\",\n    \"city_ascii\": \"Santa Fe\",\n    \"lat\": -31.6333,\n    \"lng\": -60.7,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Santa Fe\",\n    \"capital\": \"admin\",\n    \"population\": 405683.0,\n    \"id\": 1032817575\n  },\n  {\n    \"city\": \"San Juan\",\n    \"city_ascii\": \"San Juan\",\n    \"lat\": -31.5342,\n    \"lng\": -68.5261,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"San Juan\",\n    \"capital\": \"admin\",\n    \"population\": 471389.0,\n    \"id\": 1032869625\n  },\n  {\n    \"city\": \"Salta\",\n    \"city_ascii\": \"Salta\",\n    \"lat\": -24.7833,\n    \"lng\": -65.4167,\n    \"country\": \"Argentina\",\n    \"iso2\": \"AR\",\n    \"iso3\": \"ARG\",\n    \"admin_name\": \"Salta\",\n    \"capital\": \"admin\",\n    \"population\": 535303.0,\n    \"id\": 1032926124\n  },\n  {\n    \"city\": \"Central Coast\",\n    \"city_ascii\": \"Central Coast\",\n    \"lat\": -33.3,\n    \"lng\": 151.2,\n    \"country\": \"Australia\",\n    \"iso2\": \"AU\",\n    \"iso3\": \"AUS\",\n    \"admin_name\": \"New South Wales\",\n    \"capital\": null,\n    \"population\": 346596.0,\n    \"id\": 1036067845\n  },\n  {\n    \"city\": \"Sydney\",\n    \"city_ascii\": \"Sydney\",\n    \"lat\": -33.8678,\n    \"lng\": 151.21,\n    \"country\": \"Australia\",\n    \"iso2\": \"AU\",\n    \"iso3\": \"AUS\",\n    \"admin_name\": \"New South Wales\",\n    \"capital\": \"admin\",\n    \"population\": 4840600.0,\n    \"id\": 1036074917\n  },\n  {\n    \"city\": \"Canberra\",\n    \"city_ascii\": \"Canberra\",\n    \"lat\": -35.2931,\n    \"lng\": 149.1269,\n    \"country\": \"Australia\",\n    \"iso2\": \"AU\",\n    \"iso3\": \"AUS\",\n    \"admin_name\": \"Australian Capital Territory\",\n    \"capital\": \"primary\",\n    \"population\": 381488.0,\n    \"id\": 1036142029\n  },\n  {\n    \"city\": \"Gold Coast\",\n    \"city_ascii\": \"Gold Coast\",\n    \"lat\": -28.0167,\n    \"lng\": 153.4,\n    \"country\": \"Australia\",\n    \"iso2\": \"AU\",\n    \"iso3\": \"AUS\",\n    \"admin_name\": \"Queensland\",\n    \"capital\": null,\n    \"population\": 638090.0,\n    \"id\": 1036153217\n  },\n  {\n    \"city\": \"Perth\",\n    \"city_ascii\": \"Perth\",\n    \"lat\": -31.9559,\n    \"lng\": 115.8606,\n    \"country\": \"Australia\",\n    \"iso2\": \"AU\",\n    \"iso3\": \"AUS\",\n    \"admin_name\": \"Western Australia\",\n    \"capital\": \"admin\",\n    \"population\": 2141834.0,\n    \"id\": 1036178956\n  },\n  {\n    \"city\": \"Brisbane\",\n    \"city_ascii\": \"Brisbane\",\n    \"lat\": -27.4678,\n    \"lng\": 153.0281,\n    \"country\": \"Australia\",\n    \"iso2\": \"AU\",\n    \"iso3\": \"AUS\",\n    \"admin_name\": \"Queensland\",\n    \"capital\": \"admin\",\n    \"population\": 2360241.0,\n    \"id\": 1036192929\n  },\n  {\n    \"city\": \"Melbourne\",\n    \"city_ascii\": \"Melbourne\",\n    \"lat\": -37.8142,\n    \"lng\": 144.9631,\n    \"country\": \"Australia\",\n    \"iso2\": \"AU\",\n    \"iso3\": \"AUS\",\n    \"admin_name\": \"Victoria\",\n    \"capital\": \"admin\",\n    \"population\": 4529500.0,\n    \"id\": 1036533631\n  },\n  {\n    \"city\": \"Adelaide\",\n    \"city_ascii\": \"Adelaide\",\n    \"lat\": -34.9275,\n    \"lng\": 138.6,\n    \"country\": \"Australia\",\n    \"iso2\": \"AU\",\n    \"iso3\": \"AUS\",\n    \"admin_name\": \"South Australia\",\n    \"capital\": \"admin\",\n    \"population\": 1295714.0,\n    \"id\": 1036538171\n  },\n  {\n    \"city\": \"Cranbourne\",\n    \"city_ascii\": \"Cranbourne\",\n    \"lat\": -38.0996,\n    \"lng\": 145.2834,\n    \"country\": \"Australia\",\n    \"iso2\": \"AU\",\n    \"iso3\": \"AUS\",\n    \"admin_name\": \"Victoria\",\n    \"capital\": null,\n    \"population\": 460491.0,\n    \"id\": 1036685862\n  },\n  {\n    \"city\": \"Vienna\",\n    \"city_ascii\": \"Vienna\",\n    \"lat\": 48.2083,\n    \"lng\": 16.3725,\n    \"country\": \"Austria\",\n    \"iso2\": \"AT\",\n    \"iso3\": \"AUT\",\n    \"admin_name\": \"Wien\",\n    \"capital\": \"primary\",\n    \"population\": 1973403.0,\n    \"id\": 1040261752\n  },\n  {\n    \"city\": \"Manama\",\n    \"city_ascii\": \"Manama\",\n    \"lat\": 26.225,\n    \"lng\": 50.5775,\n    \"country\": \"Bahrain\",\n    \"iso2\": \"BH\",\n    \"iso3\": \"BHR\",\n    \"admin_name\": \"Al ‘Āşimah\",\n    \"capital\": \"primary\",\n    \"population\": 436000.0,\n    \"id\": 1048989486\n  },\n  {\n    \"city\": \"Kushtia\",\n    \"city_ascii\": \"Kushtia\",\n    \"lat\": 23.9101,\n    \"lng\": 89.1231,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Khulna\",\n    \"capital\": null,\n    \"population\": 418312.0,\n    \"id\": 1050000610\n  },\n  {\n    \"city\": \"Rangapukur\",\n    \"city_ascii\": \"Rangapukur\",\n    \"lat\": 25.56,\n    \"lng\": 89.25,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Rangpur\",\n    \"capital\": null,\n    \"population\": 1031388.0,\n    \"id\": 1050032005\n  },\n  {\n    \"city\": \"Tungi\",\n    \"city_ascii\": \"Tungi\",\n    \"lat\": 23.9,\n    \"lng\": 90.41,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Dhaka\",\n    \"capital\": null,\n    \"population\": 350000.0,\n    \"id\": 1050143008\n  },\n  {\n    \"city\": \"Farīdpur\",\n    \"city_ascii\": \"Faridpur\",\n    \"lat\": 23.602,\n    \"lng\": 89.833,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Dhaka\",\n    \"capital\": null,\n    \"population\": 557632.0,\n    \"id\": 1050187264\n  },\n  {\n    \"city\": \"Mymensingh\",\n    \"city_ascii\": \"Mymensingh\",\n    \"lat\": 24.7539,\n    \"lng\": 90.4031,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Mymensingh\",\n    \"capital\": \"admin\",\n    \"population\": 576722.0,\n    \"id\": 1050399881\n  },\n  {\n    \"city\": \"Nārāyanganj\",\n    \"city_ascii\": \"Narayanganj\",\n    \"lat\": 23.62,\n    \"lng\": 90.5,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Dhaka\",\n    \"capital\": null,\n    \"population\": 1572386.0,\n    \"id\": 1050424421\n  },\n  {\n    \"city\": \"Gāzipura\",\n    \"city_ascii\": \"Gazipura\",\n    \"lat\": 23.9889,\n    \"lng\": 90.375,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Dhaka\",\n    \"capital\": null,\n    \"population\": 1199215.0,\n    \"id\": 1050449249\n  },\n  {\n    \"city\": \"Dhaka\",\n    \"city_ascii\": \"Dhaka\",\n    \"lat\": 23.7639,\n    \"lng\": 90.3889,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Dhaka\",\n    \"capital\": \"primary\",\n    \"population\": 18627000.0,\n    \"id\": 1050529279\n  },\n  {\n    \"city\": \"Rājshāhi\",\n    \"city_ascii\": \"Rajshahi\",\n    \"lat\": 24.3667,\n    \"lng\": 88.6,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Rājshāhi\",\n    \"capital\": \"admin\",\n    \"population\": 763580.0,\n    \"id\": 1050547831\n  },\n  {\n    \"city\": \"Tāngāil\",\n    \"city_ascii\": \"Tangail\",\n    \"lat\": 24.2644,\n    \"lng\": 89.9181,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Dhaka\",\n    \"capital\": null,\n    \"population\": 392300.0,\n    \"id\": 1050628940\n  },\n  {\n    \"city\": \"Sylhet\",\n    \"city_ascii\": \"Sylhet\",\n    \"lat\": 24.9,\n    \"lng\": 91.8667,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Sylhet\",\n    \"capital\": \"admin\",\n    \"population\": 479837.0,\n    \"id\": 1050646703\n  },\n  {\n    \"city\": \"Khulna\",\n    \"city_ascii\": \"Khulna\",\n    \"lat\": 22.8167,\n    \"lng\": 89.55,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Khulna\",\n    \"capital\": \"admin\",\n    \"population\": 1400689.0,\n    \"id\": 1050667339\n  },\n  {\n    \"city\": \"Chauddagram\",\n    \"city_ascii\": \"Chauddagram\",\n    \"lat\": 23.2283,\n    \"lng\": 91.3133,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Chattogram\",\n    \"capital\": null,\n    \"population\": 443648.0,\n    \"id\": 1050749168\n  },\n  {\n    \"city\": \"Chattogram\",\n    \"city_ascii\": \"Chattogram\",\n    \"lat\": 22.335,\n    \"lng\": 91.8325,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Chattogram\",\n    \"capital\": \"admin\",\n    \"population\": 7000000.0,\n    \"id\": 1050830722\n  },\n  {\n    \"city\": \"Barura\",\n    \"city_ascii\": \"Barura\",\n    \"lat\": 23.375,\n    \"lng\": 91.0583,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Chattogram\",\n    \"capital\": null,\n    \"population\": 473590.0,\n    \"id\": 1050831924\n  },\n  {\n    \"city\": \"Bogra\",\n    \"city_ascii\": \"Bogra\",\n    \"lat\": 24.85,\n    \"lng\": 89.3667,\n    \"country\": \"Bangladesh\",\n    \"iso2\": \"BD\",\n    \"iso3\": \"BGD\",\n    \"admin_name\": \"Rājshāhi\",\n    \"capital\": null,\n    \"population\": 400983.0,\n    \"id\": 1050833664\n  },\n  {\n    \"city\": \"Yerevan\",\n    \"city_ascii\": \"Yerevan\",\n    \"lat\": 40.1814,\n    \"lng\": 44.5144,\n    \"country\": \"Armenia\",\n    \"iso2\": \"AM\",\n    \"iso3\": \"ARM\",\n    \"admin_name\": \"Yerevan\",\n    \"capital\": \"primary\",\n    \"population\": 1075800.0,\n    \"id\": 1051074169\n  },\n  {\n    \"city\": \"Antwerp\",\n    \"city_ascii\": \"Antwerp\",\n    \"lat\": 51.2178,\n    \"lng\": 4.4003,\n    \"country\": \"Belgium\",\n    \"iso2\": \"BE\",\n    \"iso3\": \"BEL\",\n    \"admin_name\": \"Flanders\",\n    \"capital\": \"minor\",\n    \"population\": 529247.0,\n    \"id\": 1056168623\n  },\n  {\n    \"city\": \"Brussels\",\n    \"city_ascii\": \"Brussels\",\n    \"lat\": 50.8467,\n    \"lng\": 4.3525,\n    \"country\": \"Belgium\",\n    \"iso2\": \"BE\",\n    \"iso3\": \"BEL\",\n    \"admin_name\": \"Brussels-Capital Region\",\n    \"capital\": \"primary\",\n    \"population\": 1743000.0,\n    \"id\": 1056469830\n  },\n  {\n    \"city\": \"La Paz\",\n    \"city_ascii\": \"La Paz\",\n    \"lat\": -16.5,\n    \"lng\": -68.15,\n    \"country\": \"Bolivia\",\n    \"iso2\": \"BO\",\n    \"iso3\": \"BOL\",\n    \"admin_name\": \"La Paz\",\n    \"capital\": \"primary\",\n    \"population\": 2867504.0,\n    \"id\": 1068000064\n  },\n  {\n    \"city\": \"El Alto\",\n    \"city_ascii\": \"El Alto\",\n    \"lat\": -16.5047,\n    \"lng\": -68.1633,\n    \"country\": \"Bolivia\",\n    \"iso2\": \"BO\",\n    \"iso3\": \"BOL\",\n    \"admin_name\": \"La Paz\",\n    \"capital\": null,\n    \"population\": 943000.0,\n    \"id\": 1068007058\n  },\n  {\n    \"city\": \"Santa Cruz\",\n    \"city_ascii\": \"Santa Cruz\",\n    \"lat\": -17.7892,\n    \"lng\": -63.1975,\n    \"country\": \"Bolivia\",\n    \"iso2\": \"BO\",\n    \"iso3\": \"BOL\",\n    \"admin_name\": \"Santa Cruz\",\n    \"capital\": \"admin\",\n    \"population\": 3151676.0,\n    \"id\": 1068129363\n  },\n  {\n    \"city\": \"Oruro\",\n    \"city_ascii\": \"Oruro\",\n    \"lat\": -17.9667,\n    \"lng\": -67.1167,\n    \"country\": \"Bolivia\",\n    \"iso2\": \"BO\",\n    \"iso3\": \"BOL\",\n    \"admin_name\": \"Oruro\",\n    \"capital\": null,\n    \"population\": 351802.0,\n    \"id\": 1068626742\n  },\n  {\n    \"city\": \"Cochabamba\",\n    \"city_ascii\": \"Cochabamba\",\n    \"lat\": -17.3833,\n    \"lng\": -66.1667,\n    \"country\": \"Bolivia\",\n    \"iso2\": \"BO\",\n    \"iso3\": \"BOL\",\n    \"admin_name\": \"Cochabamba\",\n    \"capital\": \"admin\",\n    \"population\": 856198.0,\n    \"id\": 1068793894\n  },\n  {\n    \"city\": \"Sarajevo\",\n    \"city_ascii\": \"Sarajevo\",\n    \"lat\": 43.8564,\n    \"lng\": 18.4131,\n    \"country\": \"Bosnia and Herzegovina\",\n    \"iso2\": \"BA\",\n    \"iso3\": \"BIH\",\n    \"admin_name\": \"Bosnia and Herzegovina, Federation of\",\n    \"capital\": \"primary\",\n    \"population\": 419957.0,\n    \"id\": 1070966777\n  },\n  {\n    \"city\": \"Jaboatão\",\n    \"city_ascii\": \"Jaboatao\",\n    \"lat\": -8.1803,\n    \"lng\": -35.0014,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Pernambuco\",\n    \"capital\": null,\n    \"population\": 702621.0,\n    \"id\": 1076000699\n  },\n  {\n    \"city\": \"Juiz de Fora\",\n    \"city_ascii\": \"Juiz de Fora\",\n    \"lat\": -21.7619,\n    \"lng\": -43.3494,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Minas Gerais\",\n    \"capital\": null,\n    \"population\": 573285.0,\n    \"id\": 1076006144\n  },\n  {\n    \"city\": \"Maringá\",\n    \"city_ascii\": \"Maringa\",\n    \"lat\": -23.4,\n    \"lng\": -51.9167,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Paraná\",\n    \"capital\": null,\n    \"population\": 403063.0,\n    \"id\": 1076013378\n  },\n  {\n    \"city\": \"Ananindeua\",\n    \"city_ascii\": \"Ananindeua\",\n    \"lat\": -1.3658,\n    \"lng\": -48.3719,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Pará\",\n    \"capital\": null,\n    \"population\": 540410.0,\n    \"id\": 1076025295\n  },\n  {\n    \"city\": \"Santos\",\n    \"city_ascii\": \"Santos\",\n    \"lat\": -23.9369,\n    \"lng\": -46.325,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 1897551.0,\n    \"id\": 1076033299\n  },\n  {\n    \"city\": \"Goiânia\",\n    \"city_ascii\": \"Goiania\",\n    \"lat\": -16.6667,\n    \"lng\": -49.25,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Goiás\",\n    \"capital\": \"admin\",\n    \"population\": 1393575.0,\n    \"id\": 1076034054\n  },\n  {\n    \"city\": \"Porto Velho\",\n    \"city_ascii\": \"Porto Velho\",\n    \"lat\": -8.7619,\n    \"lng\": -63.9039,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Rondônia\",\n    \"capital\": \"admin\",\n    \"population\": 428527.0,\n    \"id\": 1076045591\n  },\n  {\n    \"city\": \"Joinvile\",\n    \"city_ascii\": \"Joinvile\",\n    \"lat\": -26.3204,\n    \"lng\": -48.8437,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Santa Catarina\",\n    \"capital\": null,\n    \"population\": 515288.0,\n    \"id\": 1076050637\n  },\n  {\n    \"city\": \"Cuiabá\",\n    \"city_ascii\": \"Cuiaba\",\n    \"lat\": -15.5958,\n    \"lng\": -56.0969,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Mato Grosso\",\n    \"capital\": \"admin\",\n    \"population\": 585367.0,\n    \"id\": 1076112309\n  },\n  {\n    \"city\": \"Montes Claros\",\n    \"city_ascii\": \"Montes Claros\",\n    \"lat\": -16.7306,\n    \"lng\": -43.8639,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Minas Gerais\",\n    \"capital\": null,\n    \"population\": 361915.0,\n    \"id\": 1076113275\n  },\n  {\n    \"city\": \"Recife\",\n    \"city_ascii\": \"Recife\",\n    \"lat\": -8.05,\n    \"lng\": -34.9,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Pernambuco\",\n    \"capital\": \"admin\",\n    \"population\": 1653461.0,\n    \"id\": 1076137337\n  },\n  {\n    \"city\": \"Brasília\",\n    \"city_ascii\": \"Brasilia\",\n    \"lat\": -15.7939,\n    \"lng\": -47.8828,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Distrito Federal\",\n    \"capital\": \"primary\",\n    \"population\": 3039444.0,\n    \"id\": 1076144436\n  },\n  {\n    \"city\": \"Campinas\",\n    \"city_ascii\": \"Campinas\",\n    \"lat\": -22.9058,\n    \"lng\": -47.0608,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 1213792.0,\n    \"id\": 1076145766\n  },\n  {\n    \"city\": \"Piracicaba\",\n    \"city_ascii\": \"Piracicaba\",\n    \"lat\": -22.7253,\n    \"lng\": -47.6492,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 391449.0,\n    \"id\": 1076166252\n  },\n  {\n    \"city\": \"Macapá\",\n    \"city_ascii\": \"Macapa\",\n    \"lat\": 0.033,\n    \"lng\": -51.0653,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Amapá\",\n    \"capital\": \"admin\",\n    \"population\": 512902.0,\n    \"id\": 1076189884\n  },\n  {\n    \"city\": \"Florianópolis\",\n    \"city_ascii\": \"Florianopolis\",\n    \"lat\": -27.6122,\n    \"lng\": -48.4853,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Santa Catarina\",\n    \"capital\": \"admin\",\n    \"population\": 477798.0,\n    \"id\": 1076190259\n  },\n  {\n    \"city\": \"Serra\",\n    \"city_ascii\": \"Serra\",\n    \"lat\": -20.1289,\n    \"lng\": -40.3078,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Espírito Santo\",\n    \"capital\": null,\n    \"population\": 485376.0,\n    \"id\": 1076191325\n  },\n  {\n    \"city\": \"Anápolis\",\n    \"city_ascii\": \"Anapolis\",\n    \"lat\": -16.3339,\n    \"lng\": -48.9519,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Goiás\",\n    \"capital\": null,\n    \"population\": 366491.0,\n    \"id\": 1076208869\n  },\n  {\n    \"city\": \"Campina Grande\",\n    \"city_ascii\": \"Campina Grande\",\n    \"lat\": -7.2306,\n    \"lng\": -35.8811,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Paraíba\",\n    \"capital\": null,\n    \"population\": 405072.0,\n    \"id\": 1076218697\n  },\n  {\n    \"city\": \"Natal\",\n    \"city_ascii\": \"Natal\",\n    \"lat\": -6.9838,\n    \"lng\": -60.2699,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Amazonas\",\n    \"capital\": null,\n    \"population\": 980588.0,\n    \"id\": 1076336975\n  },\n  {\n    \"city\": \"Iguaçu\",\n    \"city_ascii\": \"Iguacu\",\n    \"lat\": -22.74,\n    \"lng\": -43.47,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Rio de Janeiro\",\n    \"capital\": null,\n    \"population\": 844583.0,\n    \"id\": 1076339714\n  },\n  {\n    \"city\": \"Vitória\",\n    \"city_ascii\": \"Vitoria\",\n    \"lat\": -20.2889,\n    \"lng\": -40.3083,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Espírito Santo\",\n    \"capital\": \"admin\",\n    \"population\": 355875.0,\n    \"id\": 1076376829\n  },\n  {\n    \"city\": \"Rio Branco\",\n    \"city_ascii\": \"Rio Branco\",\n    \"lat\": -9.9747,\n    \"lng\": -67.81,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Acre\",\n    \"capital\": \"admin\",\n    \"population\": 413418.0,\n    \"id\": 1076391263\n  },\n  {\n    \"city\": \"Caruaru\",\n    \"city_ascii\": \"Caruaru\",\n    \"lat\": -8.2828,\n    \"lng\": -35.9758,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Pernambuco\",\n    \"capital\": null,\n    \"population\": 347088.0,\n    \"id\": 1076397475\n  },\n  {\n    \"city\": \"Vila Velha\",\n    \"city_ascii\": \"Vila Velha\",\n    \"lat\": -20.3364,\n    \"lng\": -40.2936,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Espírito Santo\",\n    \"capital\": null,\n    \"population\": 472762.0,\n    \"id\": 1076404077\n  },\n  {\n    \"city\": \"Abaeté\",\n    \"city_ascii\": \"Abaete\",\n    \"lat\": -19.1583,\n    \"lng\": -45.4522,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Minas Gerais\",\n    \"capital\": null,\n    \"population\": 800000.0,\n    \"id\": 1076413528\n  },\n  {\n    \"city\": \"Maceió\",\n    \"city_ascii\": \"Maceio\",\n    \"lat\": -9.6658,\n    \"lng\": -35.735,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Alagoas\",\n    \"capital\": \"admin\",\n    \"population\": 1025360.0,\n    \"id\": 1076440479\n  },\n  {\n    \"city\": \"Mauá\",\n    \"city_ascii\": \"Maua\",\n    \"lat\": -23.6678,\n    \"lng\": -46.4608,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 453286.0,\n    \"id\": 1076477498\n  },\n  {\n    \"city\": \"Cariacica\",\n    \"city_ascii\": \"Cariacica\",\n    \"lat\": -20.2639,\n    \"lng\": -40.42,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Espírito Santo\",\n    \"capital\": null,\n    \"population\": 348738.0,\n    \"id\": 1076479479\n  },\n  {\n    \"city\": \"São Gonçalo\",\n    \"city_ascii\": \"Sao Goncalo\",\n    \"lat\": -22.8269,\n    \"lng\": -43.0539,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Rio de Janeiro\",\n    \"capital\": null,\n    \"population\": 1077687.0,\n    \"id\": 1076485783\n  },\n  {\n    \"city\": \"Uberlândia\",\n    \"city_ascii\": \"Uberlandia\",\n    \"lat\": -18.9231,\n    \"lng\": -48.2886,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Minas Gerais\",\n    \"capital\": null,\n    \"population\": 604013.0,\n    \"id\": 1076495001\n  },\n  {\n    \"city\": \"Niterói\",\n    \"city_ascii\": \"Niteroi\",\n    \"lat\": -22.8833,\n    \"lng\": -43.1036,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Rio de Janeiro\",\n    \"capital\": null,\n    \"population\": 496696.0,\n    \"id\": 1076501425\n  },\n  {\n    \"city\": \"Ribeirão Prêto\",\n    \"city_ascii\": \"Ribeirao Preto\",\n    \"lat\": -21.1783,\n    \"lng\": -47.8067,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 711825.0,\n    \"id\": 1076524478\n  },\n  {\n    \"city\": \"Aracaju\",\n    \"city_ascii\": \"Aracaju\",\n    \"lat\": -10.9167,\n    \"lng\": -37.05,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Sergipe\",\n    \"capital\": \"admin\",\n    \"population\": 632744.0,\n    \"id\": 1076527830\n  },\n  {\n    \"city\": \"São Paulo\",\n    \"city_ascii\": \"Sao Paulo\",\n    \"lat\": -23.55,\n    \"lng\": -46.6333,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": \"admin\",\n    \"population\": 23086000.0,\n    \"id\": 1076532519\n  },\n  {\n    \"city\": \"Fortaleza\",\n    \"city_ascii\": \"Fortaleza\",\n    \"lat\": -3.7275,\n    \"lng\": -38.5275,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Ceará\",\n    \"capital\": \"admin\",\n    \"population\": 2452185.0,\n    \"id\": 1076567885\n  },\n  {\n    \"city\": \"Vila Velha\",\n    \"city_ascii\": \"Vila Velha\",\n    \"lat\": 3.2167,\n    \"lng\": -51.2167,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Amapá\",\n    \"capital\": null,\n    \"population\": 1209091.0,\n    \"id\": 1076575691\n  },\n  {\n    \"city\": \"Campos\",\n    \"city_ascii\": \"Campos\",\n    \"lat\": -21.7539,\n    \"lng\": -41.3239,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Rio de Janeiro\",\n    \"capital\": null,\n    \"population\": 463731.0,\n    \"id\": 1076606365\n  },\n  {\n    \"city\": \"Manaus\",\n    \"city_ascii\": \"Manaus\",\n    \"lat\": -3.1,\n    \"lng\": -60.0167,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Amazonas\",\n    \"capital\": \"admin\",\n    \"population\": 2219580.0,\n    \"id\": 1076607274\n  },\n  {\n    \"city\": \"Blumenau\",\n    \"city_ascii\": \"Blumenau\",\n    \"lat\": -26.9333,\n    \"lng\": -49.05,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Santa Catarina\",\n    \"capital\": null,\n    \"population\": 361855.0,\n    \"id\": 1076618665\n  },\n  {\n    \"city\": \"Boa Vista\",\n    \"city_ascii\": \"Boa Vista\",\n    \"lat\": 2.8194,\n    \"lng\": -60.6714,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Roraima\",\n    \"capital\": \"admin\",\n    \"population\": 419652.0,\n    \"id\": 1076621300\n  },\n  {\n    \"city\": \"Santo André\",\n    \"city_ascii\": \"Santo Andre\",\n    \"lat\": -23.6572,\n    \"lng\": -46.5333,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 721368.0,\n    \"id\": 1076625886\n  },\n  {\n    \"city\": \"Belém\",\n    \"city_ascii\": \"Belem\",\n    \"lat\": -1.4558,\n    \"lng\": -48.5039,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Pará\",\n    \"capital\": \"admin\",\n    \"population\": 1499641.0,\n    \"id\": 1076646823\n  },\n  {\n    \"city\": \"Porto Alegre\",\n    \"city_ascii\": \"Porto Alegre\",\n    \"lat\": -30.0331,\n    \"lng\": -51.23,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Rio Grande do Sul\",\n    \"capital\": \"admin\",\n    \"population\": 1484941.0,\n    \"id\": 1076658221\n  },\n  {\n    \"city\": \"Campo Grande\",\n    \"city_ascii\": \"Campo Grande\",\n    \"lat\": -20.4839,\n    \"lng\": -54.615,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Mato Grosso do Sul\",\n    \"capital\": \"admin\",\n    \"population\": 906092.0,\n    \"id\": 1076660445\n  },\n  {\n    \"city\": \"Natal\",\n    \"city_ascii\": \"Natal\",\n    \"lat\": -5.7833,\n    \"lng\": -35.2,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Rio Grande do Norte\",\n    \"capital\": \"admin\",\n    \"population\": 877662.0,\n    \"id\": 1076697777\n  },\n  {\n    \"city\": \"Curitiba\",\n    \"city_ascii\": \"Curitiba\",\n    \"lat\": -25.4297,\n    \"lng\": -49.2711,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Paraná\",\n    \"capital\": \"admin\",\n    \"population\": 1879355.0,\n    \"id\": 1076701712\n  },\n  {\n    \"city\": \"Londrina\",\n    \"city_ascii\": \"Londrina\",\n    \"lat\": -23.31,\n    \"lng\": -51.1628,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Paraná\",\n    \"capital\": null,\n    \"population\": 548249.0,\n    \"id\": 1076723241\n  },\n  {\n    \"city\": \"Teresina\",\n    \"city_ascii\": \"Teresina\",\n    \"lat\": -5.0949,\n    \"lng\": -42.8042,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Piauí\",\n    \"capital\": \"admin\",\n    \"population\": 953172.0,\n    \"id\": 1076727667\n  },\n  {\n    \"city\": \"Guarulhos\",\n    \"city_ascii\": \"Guarulhos\",\n    \"lat\": -23.4628,\n    \"lng\": -46.5328,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 1324781.0,\n    \"id\": 1076730420\n  },\n  {\n    \"city\": \"Franca\",\n    \"city_ascii\": \"Franca\",\n    \"lat\": -20.5389,\n    \"lng\": -47.4008,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 358539.0,\n    \"id\": 1076740256\n  },\n  {\n    \"city\": \"Sorocaba\",\n    \"city_ascii\": \"Sorocaba\",\n    \"lat\": -23.5017,\n    \"lng\": -47.4581,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 644919.0,\n    \"id\": 1076758708\n  },\n  {\n    \"city\": \"São José do Rio Prêto\",\n    \"city_ascii\": \"Sao Jose do Rio Preto\",\n    \"lat\": -20.8081,\n    \"lng\": -49.3811,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 469173.0,\n    \"id\": 1076760827\n  },\n  {\n    \"city\": \"São José dos Campos\",\n    \"city_ascii\": \"Sao Jose dos Campos\",\n    \"lat\": -23.1789,\n    \"lng\": -45.8869,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 729737.0,\n    \"id\": 1076783887\n  },\n  {\n    \"city\": \"Olinda\",\n    \"city_ascii\": \"Olinda\",\n    \"lat\": -8.0,\n    \"lng\": -34.8833,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Pernambuco\",\n    \"capital\": null,\n    \"population\": 393115.0,\n    \"id\": 1076784718\n  },\n  {\n    \"city\": \"Osasco\",\n    \"city_ascii\": \"Osasco\",\n    \"lat\": -23.5328,\n    \"lng\": -46.7919,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 694844.0,\n    \"id\": 1076786452\n  },\n  {\n    \"city\": \"São Bernardo do Campo\",\n    \"city_ascii\": \"Sao Bernardo do Campo\",\n    \"lat\": -23.7,\n    \"lng\": -46.55,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 816925.0,\n    \"id\": 1076793227\n  },\n  {\n    \"city\": \"Caxias do Sul\",\n    \"city_ascii\": \"Caxias do Sul\",\n    \"lat\": -29.1667,\n    \"lng\": -51.1833,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Rio Grande do Sul\",\n    \"capital\": null,\n    \"population\": 435564.0,\n    \"id\": 1076809957\n  },\n  {\n    \"city\": \"Vitória da Conquista\",\n    \"city_ascii\": \"Vitoria da Conquista\",\n    \"lat\": -14.8658,\n    \"lng\": -40.8389,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Bahia\",\n    \"capital\": null,\n    \"population\": 343230.0,\n    \"id\": 1076812020\n  },\n  {\n    \"city\": \"São Luís\",\n    \"city_ascii\": \"Sao Luis\",\n    \"lat\": -2.5283,\n    \"lng\": -44.3044,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Maranhão\",\n    \"capital\": \"admin\",\n    \"population\": 1108975.0,\n    \"id\": 1076819308\n  },\n  {\n    \"city\": \"Contagem\",\n    \"city_ascii\": \"Contagem\",\n    \"lat\": -19.9319,\n    \"lng\": -44.0539,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Minas Gerais\",\n    \"capital\": null,\n    \"population\": 648766.0,\n    \"id\": 1076845191\n  },\n  {\n    \"city\": \"São Vicente\",\n    \"city_ascii\": \"Sao Vicente\",\n    \"lat\": -23.9633,\n    \"lng\": -46.3922,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 355542.0,\n    \"id\": 1076857089\n  },\n  {\n    \"city\": \"Mogi das Cruzes\",\n    \"city_ascii\": \"Mogi das Cruzes\",\n    \"lat\": -23.5228,\n    \"lng\": -46.1878,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 450785.0,\n    \"id\": 1076857883\n  },\n  {\n    \"city\": \"Diadema\",\n    \"city_ascii\": \"Diadema\",\n    \"lat\": -23.6861,\n    \"lng\": -46.6106,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 426757.0,\n    \"id\": 1076867279\n  },\n  {\n    \"city\": \"Caucaia\",\n    \"city_ascii\": \"Caucaia\",\n    \"lat\": -3.7167,\n    \"lng\": -38.65,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Ceará\",\n    \"capital\": null,\n    \"population\": 368918.0,\n    \"id\": 1076870058\n  },\n  {\n    \"city\": \"Carapicuíba\",\n    \"city_ascii\": \"Carapicuiba\",\n    \"lat\": -23.5192,\n    \"lng\": -46.8358,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 403183.0,\n    \"id\": 1076874103\n  },\n  {\n    \"city\": \"Rio de Janeiro\",\n    \"city_ascii\": \"Rio de Janeiro\",\n    \"lat\": -22.9111,\n    \"lng\": -43.2056,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Rio de Janeiro\",\n    \"capital\": \"admin\",\n    \"population\": 12592000.0,\n    \"id\": 1076887657\n  },\n  {\n    \"city\": \"Feira de Santana\",\n    \"city_ascii\": \"Feira de Santana\",\n    \"lat\": -12.25,\n    \"lng\": -38.95,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Bahia\",\n    \"capital\": null,\n    \"population\": 617528.0,\n    \"id\": 1076892244\n  },\n  {\n    \"city\": \"Bauru\",\n    \"city_ascii\": \"Bauru\",\n    \"lat\": -22.315,\n    \"lng\": -49.0608,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 366992.0,\n    \"id\": 1076905338\n  },\n  {\n    \"city\": \"João Pessoa\",\n    \"city_ascii\": \"Joao Pessoa\",\n    \"lat\": -7.12,\n    \"lng\": -34.88,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Paraíba\",\n    \"capital\": \"admin\",\n    \"population\": 801718.0,\n    \"id\": 1076922014\n  },\n  {\n    \"city\": \"Salvador\",\n    \"city_ascii\": \"Salvador\",\n    \"lat\": -12.9747,\n    \"lng\": -38.4767,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Bahia\",\n    \"capital\": \"admin\",\n    \"population\": 2886698.0,\n    \"id\": 1076923789\n  },\n  {\n    \"city\": \"Itaquaquecetuba\",\n    \"city_ascii\": \"Itaquaquecetuba\",\n    \"lat\": -23.4864,\n    \"lng\": -46.3486,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 352801.0,\n    \"id\": 1076942224\n  },\n  {\n    \"city\": \"Betim\",\n    \"city_ascii\": \"Betim\",\n    \"lat\": -19.9678,\n    \"lng\": -44.1978,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Minas Gerais\",\n    \"capital\": null,\n    \"population\": 378089.0,\n    \"id\": 1076953384\n  },\n  {\n    \"city\": \"Belo Horizonte\",\n    \"city_ascii\": \"Belo Horizonte\",\n    \"lat\": -19.9167,\n    \"lng\": -43.9333,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"Minas Gerais\",\n    \"capital\": \"admin\",\n    \"population\": 5328000.0,\n    \"id\": 1076967355\n  },\n  {\n    \"city\": \"Jundiaí\",\n    \"city_ascii\": \"Jundiai\",\n    \"lat\": -23.1858,\n    \"lng\": -46.8839,\n    \"country\": \"Brazil\",\n    \"iso2\": \"BR\",\n    \"iso3\": \"BRA\",\n    \"admin_name\": \"São Paulo\",\n    \"capital\": null,\n    \"population\": 401896.0,\n    \"id\": 1076998392\n  },\n  {\n    \"city\": \"Plovdiv\",\n    \"city_ascii\": \"Plovdiv\",\n    \"lat\": 42.15,\n    \"lng\": 24.75,\n    \"country\": \"Bulgaria\",\n    \"iso2\": \"BG\",\n    \"iso3\": \"BGR\",\n    \"admin_name\": \"Plovdiv\",\n    \"capital\": \"admin\",\n    \"population\": 383540.0,\n    \"id\": 1100436706\n  },\n  {\n    \"city\": \"Sofia\",\n    \"city_ascii\": \"Sofia\",\n    \"lat\": 42.7,\n    \"lng\": 23.33,\n    \"country\": \"Bulgaria\",\n    \"iso2\": \"BG\",\n    \"iso3\": \"BGR\",\n    \"admin_name\": \"Sofia-Grad\",\n    \"capital\": \"primary\",\n    \"population\": 1547779.0,\n    \"id\": 1100762037\n  },\n  {\n    \"city\": \"Varna\",\n    \"city_ascii\": \"Varna\",\n    \"lat\": 43.2167,\n    \"lng\": 27.9167,\n    \"country\": \"Bulgaria\",\n    \"iso2\": \"BG\",\n    \"iso3\": \"BGR\",\n    \"admin_name\": \"Varna\",\n    \"capital\": \"admin\",\n    \"population\": 348668.0,\n    \"id\": 1100789115\n  },\n  {\n    \"city\": \"Maungdaw\",\n    \"city_ascii\": \"Maungdaw\",\n    \"lat\": 20.8167,\n    \"lng\": 92.3667,\n    \"country\": \"Myanmar\",\n    \"iso2\": \"MM\",\n    \"iso3\": \"MMR\",\n    \"admin_name\": \"Rakhine State\",\n    \"capital\": null,\n    \"population\": 400000.0,\n    \"id\": 1104000431\n  },\n  {\n    \"city\": \"Taunggyi\",\n    \"city_ascii\": \"Taunggyi\",\n    \"lat\": 20.7836,\n    \"lng\": 97.0354,\n    \"country\": \"Myanmar\",\n    \"iso2\": \"MM\",\n    \"iso3\": \"MMR\",\n    \"admin_name\": \"Shan State\",\n    \"capital\": \"admin\",\n    \"population\": 381639.0,\n    \"id\": 1104364374\n  },\n  {\n    \"city\": \"Mandalay\",\n    \"city_ascii\": \"Mandalay\",\n    \"lat\": 21.9831,\n    \"lng\": 96.0844,\n    \"country\": \"Myanmar\",\n    \"iso2\": \"MM\",\n    \"iso3\": \"MMR\",\n    \"admin_name\": \"Mandalay\",\n    \"capital\": \"admin\",\n    \"population\": 1319452.0,\n    \"id\": 1104468217\n  },\n  {\n    \"city\": \"Hpa-An\",\n    \"city_ascii\": \"Hpa-An\",\n    \"lat\": 16.8906,\n    \"lng\": 97.6333,\n    \"country\": \"Myanmar\",\n    \"iso2\": \"MM\",\n    \"iso3\": \"MMR\",\n    \"admin_name\": \"Kayin State\",\n    \"capital\": \"admin\",\n    \"population\": 421525.0,\n    \"id\": 1104494124\n  },\n  {\n    \"city\": \"Rangoon\",\n    \"city_ascii\": \"Rangoon\",\n    \"lat\": 16.795,\n    \"lng\": 96.16,\n    \"country\": \"Myanmar\",\n    \"iso2\": \"MM\",\n    \"iso3\": \"MMR\",\n    \"admin_name\": \"Yangon\",\n    \"capital\": \"primary\",\n    \"population\": 5209541.0,\n    \"id\": 1104616656\n  },\n  {\n    \"city\": \"Kyaukse\",\n    \"city_ascii\": \"Kyaukse\",\n    \"lat\": 21.6131,\n    \"lng\": 96.1303,\n    \"country\": \"Myanmar\",\n    \"iso2\": \"MM\",\n    \"iso3\": \"MMR\",\n    \"admin_name\": \"Mandalay\",\n    \"capital\": null,\n    \"population\": 741071.0,\n    \"id\": 1104814217\n  },\n  {\n    \"city\": \"Nay Pyi Taw\",\n    \"city_ascii\": \"Nay Pyi Taw\",\n    \"lat\": 19.7475,\n    \"lng\": 96.115,\n    \"country\": \"Myanmar\",\n    \"iso2\": \"MM\",\n    \"iso3\": \"MMR\",\n    \"admin_name\": \"Nay Pyi Taw\",\n    \"capital\": \"primary\",\n    \"population\": 1160242.0,\n    \"id\": 1104838105\n  },\n  {\n    \"city\": \"Bujumbura\",\n    \"city_ascii\": \"Bujumbura\",\n    \"lat\": -3.3833,\n    \"lng\": 29.3667,\n    \"country\": \"Burundi\",\n    \"iso2\": \"BI\",\n    \"iso3\": \"BDI\",\n    \"admin_name\": \"Bujumbura Mairie\",\n    \"capital\": \"primary\",\n    \"population\": 1075000.0,\n    \"id\": 1108101689\n  },\n  {\n    \"city\": \"Hrodna\",\n    \"city_ascii\": \"Hrodna\",\n    \"lat\": 53.6667,\n    \"lng\": 23.8333,\n    \"country\": \"Belarus\",\n    \"iso2\": \"BY\",\n    \"iso3\": \"BLR\",\n    \"admin_name\": \"Hrodzyenskaya Voblasts’\",\n    \"capital\": \"admin\",\n    \"population\": 357493.0,\n    \"id\": 1112187197\n  },\n  {\n    \"city\": \"Minsk\",\n    \"city_ascii\": \"Minsk\",\n    \"lat\": 53.9,\n    \"lng\": 27.5667,\n    \"country\": \"Belarus\",\n    \"iso2\": \"BY\",\n    \"iso3\": \"BLR\",\n    \"admin_name\": \"Minsk\",\n    \"capital\": \"primary\",\n    \"population\": 2009786.0,\n    \"id\": 1112348503\n  },\n  {\n    \"city\": \"Vitsyebsk\",\n    \"city_ascii\": \"Vitsyebsk\",\n    \"lat\": 55.1917,\n    \"lng\": 30.2056,\n    \"country\": \"Belarus\",\n    \"iso2\": \"BY\",\n    \"iso3\": \"BLR\",\n    \"admin_name\": \"Vitsyebskaya Voblasts’\",\n    \"capital\": \"admin\",\n    \"population\": 366299.0,\n    \"id\": 1112480679\n  },\n  {\n    \"city\": \"Mahilyow\",\n    \"city_ascii\": \"Mahilyow\",\n    \"lat\": 53.9167,\n    \"lng\": 30.35,\n    \"country\": \"Belarus\",\n    \"iso2\": \"BY\",\n    \"iso3\": \"BLR\",\n    \"admin_name\": \"Mahilyowskaya Voblasts’\",\n    \"capital\": \"admin\",\n    \"population\": 357100.0,\n    \"id\": 1112518993\n  },\n  {\n    \"city\": \"Homyel’\",\n    \"city_ascii\": \"Homyel'\",\n    \"lat\": 52.4453,\n    \"lng\": 30.9842,\n    \"country\": \"Belarus\",\n    \"iso2\": \"BY\",\n    \"iso3\": \"BLR\",\n    \"admin_name\": \"Homyel’skaya Voblasts’\",\n    \"capital\": \"admin\",\n    \"population\": 510300.0,\n    \"id\": 1112580227\n  },\n  {\n    \"city\": \"Brest\",\n    \"city_ascii\": \"Brest\",\n    \"lat\": 52.1347,\n    \"lng\": 23.6569,\n    \"country\": \"Belarus\",\n    \"iso2\": \"BY\",\n    \"iso3\": \"BLR\",\n    \"admin_name\": \"Brestskaya Voblasts’\",\n    \"capital\": \"admin\",\n    \"population\": 340723.0,\n    \"id\": 1112896927\n  },\n  {\n    \"city\": \"Phnom Penh\",\n    \"city_ascii\": \"Phnom Penh\",\n    \"lat\": 11.5694,\n    \"lng\": 104.9211,\n    \"country\": \"Cambodia\",\n    \"iso2\": \"KH\",\n    \"iso3\": \"KHM\",\n    \"admin_name\": \"Phnom Penh\",\n    \"capital\": \"primary\",\n    \"population\": 2129371.0,\n    \"id\": 1116260534\n  },\n  {\n    \"city\": \"Yaoundé\",\n    \"city_ascii\": \"Yaounde\",\n    \"lat\": 3.8667,\n    \"lng\": 11.5167,\n    \"country\": \"Cameroon\",\n    \"iso2\": \"CM\",\n    \"iso3\": \"CMR\",\n    \"admin_name\": \"Centre\",\n    \"capital\": \"primary\",\n    \"population\": 2440462.0,\n    \"id\": 1120298240\n  },\n  {\n    \"city\": \"Bafoussam\",\n    \"city_ascii\": \"Bafoussam\",\n    \"lat\": 5.4667,\n    \"lng\": 10.4167,\n    \"country\": \"Cameroon\",\n    \"iso2\": \"CM\",\n    \"iso3\": \"CMR\",\n    \"admin_name\": \"Ouest\",\n    \"capital\": \"admin\",\n    \"population\": 1146000.0,\n    \"id\": 1120435460\n  },\n  {\n    \"city\": \"Douala\",\n    \"city_ascii\": \"Douala\",\n    \"lat\": 4.05,\n    \"lng\": 9.7,\n    \"country\": \"Cameroon\",\n    \"iso2\": \"CM\",\n    \"iso3\": \"CMR\",\n    \"admin_name\": \"Littoral\",\n    \"capital\": \"admin\",\n    \"population\": 5768400.0,\n    \"id\": 1120494607\n  },\n  {\n    \"city\": \"Garoua\",\n    \"city_ascii\": \"Garoua\",\n    \"lat\": 9.3,\n    \"lng\": 13.4,\n    \"country\": \"Cameroon\",\n    \"iso2\": \"CM\",\n    \"iso3\": \"CMR\",\n    \"admin_name\": \"Nord\",\n    \"capital\": \"admin\",\n    \"population\": 600000.0,\n    \"id\": 1120803808\n  },\n  {\n    \"city\": \"Bamenda\",\n    \"city_ascii\": \"Bamenda\",\n    \"lat\": 5.9614,\n    \"lng\": 10.1517,\n    \"country\": \"Cameroon\",\n    \"iso2\": \"CM\",\n    \"iso3\": \"CMR\",\n    \"admin_name\": \"North-West\",\n    \"capital\": \"admin\",\n    \"population\": 2000000.0,\n    \"id\": 1120909610\n  },\n  {\n    \"city\": \"Surrey\",\n    \"city_ascii\": \"Surrey\",\n    \"lat\": 49.19,\n    \"lng\": -122.8489,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"British Columbia\",\n    \"capital\": null,\n    \"population\": 517887.0,\n    \"id\": 1124001454\n  },\n  {\n    \"city\": \"Mississauga\",\n    \"city_ascii\": \"Mississauga\",\n    \"lat\": 43.6,\n    \"lng\": -79.65,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Ontario\",\n    \"capital\": null,\n    \"population\": 721599.0,\n    \"id\": 1124112672\n  },\n  {\n    \"city\": \"Halifax\",\n    \"city_ascii\": \"Halifax\",\n    \"lat\": 44.6475,\n    \"lng\": -63.5906,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Nova Scotia\",\n    \"capital\": \"admin\",\n    \"population\": 403131.0,\n    \"id\": 1124130981\n  },\n  {\n    \"city\": \"Kitchener\",\n    \"city_ascii\": \"Kitchener\",\n    \"lat\": 43.4186,\n    \"lng\": -80.4728,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Ontario\",\n    \"capital\": null,\n    \"population\": 470015.0,\n    \"id\": 1124158530\n  },\n  {\n    \"city\": \"Winnipeg\",\n    \"city_ascii\": \"Winnipeg\",\n    \"lat\": 49.8844,\n    \"lng\": -97.1464,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Manitoba\",\n    \"capital\": \"admin\",\n    \"population\": 705244.0,\n    \"id\": 1124224963\n  },\n  {\n    \"city\": \"Toronto\",\n    \"city_ascii\": \"Toronto\",\n    \"lat\": 43.7417,\n    \"lng\": -79.3733,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Ontario\",\n    \"capital\": \"admin\",\n    \"population\": 5429524.0,\n    \"id\": 1124279679\n  },\n  {\n    \"city\": \"Edmonton\",\n    \"city_ascii\": \"Edmonton\",\n    \"lat\": 53.5344,\n    \"lng\": -113.4903,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Alberta\",\n    \"capital\": \"admin\",\n    \"population\": 1062643.0,\n    \"id\": 1124290735\n  },\n  {\n    \"city\": \"Ottawa\",\n    \"city_ascii\": \"Ottawa\",\n    \"lat\": 45.4247,\n    \"lng\": -75.695,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Ontario\",\n    \"capital\": \"primary\",\n    \"population\": 989567.0,\n    \"id\": 1124399363\n  },\n  {\n    \"city\": \"London\",\n    \"city_ascii\": \"London\",\n    \"lat\": 42.9836,\n    \"lng\": -81.2497,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Ontario\",\n    \"capital\": null,\n    \"population\": 383822.0,\n    \"id\": 1124469960\n  },\n  {\n    \"city\": \"Hamilton\",\n    \"city_ascii\": \"Hamilton\",\n    \"lat\": 43.2567,\n    \"lng\": -79.8692,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Ontario\",\n    \"capital\": null,\n    \"population\": 693645.0,\n    \"id\": 1124567288\n  },\n  {\n    \"city\": \"Montréal\",\n    \"city_ascii\": \"Montreal\",\n    \"lat\": 45.5089,\n    \"lng\": -73.5617,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Quebec\",\n    \"capital\": null,\n    \"population\": 3519595.0,\n    \"id\": 1124586170\n  },\n  {\n    \"city\": \"Brampton\",\n    \"city_ascii\": \"Brampton\",\n    \"lat\": 43.6833,\n    \"lng\": -79.7667,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Ontario\",\n    \"capital\": null,\n    \"population\": 593638.0,\n    \"id\": 1124625989\n  },\n  {\n    \"city\": \"Calgary\",\n    \"city_ascii\": \"Calgary\",\n    \"lat\": 51.05,\n    \"lng\": -114.0667,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Alberta\",\n    \"capital\": null,\n    \"population\": 1239220.0,\n    \"id\": 1124690423\n  },\n  {\n    \"city\": \"Quebec City\",\n    \"city_ascii\": \"Quebec City\",\n    \"lat\": 46.8139,\n    \"lng\": -71.2081,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Quebec\",\n    \"capital\": \"admin\",\n    \"population\": 705103.0,\n    \"id\": 1124823933\n  },\n  {\n    \"city\": \"Vancouver\",\n    \"city_ascii\": \"Vancouver\",\n    \"lat\": 49.25,\n    \"lng\": -123.1,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"British Columbia\",\n    \"capital\": null,\n    \"population\": 2264823.0,\n    \"id\": 1124825478\n  },\n  {\n    \"city\": \"Laval\",\n    \"city_ascii\": \"Laval\",\n    \"lat\": 45.5833,\n    \"lng\": -73.75,\n    \"country\": \"Canada\",\n    \"iso2\": \"CA\",\n    \"iso3\": \"CAN\",\n    \"admin_name\": \"Quebec\",\n    \"capital\": null,\n    \"population\": 422993.0,\n    \"id\": 1124922301\n  },\n  {\n    \"city\": \"Bangui\",\n    \"city_ascii\": \"Bangui\",\n    \"lat\": 4.3733,\n    \"lng\": 18.5628,\n    \"country\": \"Central African Republic\",\n    \"iso2\": \"CF\",\n    \"iso3\": \"CAF\",\n    \"admin_name\": \"Bangui\",\n    \"capital\": \"primary\",\n    \"population\": 889231.0,\n    \"id\": 1140080881\n  },\n  {\n    \"city\": \"Colombo\",\n    \"city_ascii\": \"Colombo\",\n    \"lat\": 6.9344,\n    \"lng\": 79.8428,\n    \"country\": \"Sri Lanka\",\n    \"iso2\": \"LK\",\n    \"iso3\": \"LKA\",\n    \"admin_name\": \"Western\",\n    \"capital\": \"primary\",\n    \"population\": 2323826.0,\n    \"id\": 1144251314\n  },\n  {\n    \"city\": \"N’Djamena\",\n    \"city_ascii\": \"N'Djamena\",\n    \"lat\": 12.11,\n    \"lng\": 15.05,\n    \"country\": \"Chad\",\n    \"iso2\": \"TD\",\n    \"iso3\": \"TCD\",\n    \"admin_name\": \"N’Djamena\",\n    \"capital\": \"primary\",\n    \"population\": 1092066.0,\n    \"id\": 1148708596\n  },\n  {\n    \"city\": \"Puente Alto\",\n    \"city_ascii\": \"Puente Alto\",\n    \"lat\": -33.6167,\n    \"lng\": -70.5667,\n    \"country\": \"Chile\",\n    \"iso2\": \"CL\",\n    \"iso3\": \"CHL\",\n    \"admin_name\": \"Región Metropolitana\",\n    \"capital\": \"minor\",\n    \"population\": 573935.0,\n    \"id\": 1152516346\n  },\n  {\n    \"city\": \"Santiago\",\n    \"city_ascii\": \"Santiago\",\n    \"lat\": -33.4372,\n    \"lng\": -70.6506,\n    \"country\": \"Chile\",\n    \"iso2\": \"CL\",\n    \"iso3\": \"CHL\",\n    \"admin_name\": \"Región Metropolitana\",\n    \"capital\": \"primary\",\n    \"population\": 7171000.0,\n    \"id\": 1152554349\n  },\n  {\n    \"city\": \"Maipú\",\n    \"city_ascii\": \"Maipu\",\n    \"lat\": -33.5167,\n    \"lng\": -70.7667,\n    \"country\": \"Chile\",\n    \"iso2\": \"CL\",\n    \"iso3\": \"CHL\",\n    \"admin_name\": \"Región Metropolitana\",\n    \"capital\": null,\n    \"population\": 521627.0,\n    \"id\": 1152583016\n  },\n  {\n    \"city\": \"Antofagasta\",\n    \"city_ascii\": \"Antofagasta\",\n    \"lat\": -23.65,\n    \"lng\": -70.4,\n    \"country\": \"Chile\",\n    \"iso2\": \"CL\",\n    \"iso3\": \"CHL\",\n    \"admin_name\": \"Antofagasta\",\n    \"capital\": \"admin\",\n    \"population\": 348517.0,\n    \"id\": 1152734289\n  },\n  {\n    \"city\": \"Concepción\",\n    \"city_ascii\": \"Concepcion\",\n    \"lat\": -36.8282,\n    \"lng\": -73.0514,\n    \"country\": \"Chile\",\n    \"iso2\": \"CL\",\n    \"iso3\": \"CHL\",\n    \"admin_name\": \"Biobío\",\n    \"capital\": \"admin\",\n    \"population\": 719944.0,\n    \"id\": 1152838958\n  },\n  {\n    \"city\": \"La Florida\",\n    \"city_ascii\": \"La Florida\",\n    \"lat\": -33.5333,\n    \"lng\": -70.5833,\n    \"country\": \"Chile\",\n    \"iso2\": \"CL\",\n    \"iso3\": \"CHL\",\n    \"admin_name\": \"Región Metropolitana\",\n    \"capital\": null,\n    \"population\": 366916.0,\n    \"id\": 1152939649\n  },\n  {\n    \"city\": \"Cencheng\",\n    \"city_ascii\": \"Cencheng\",\n    \"lat\": 22.9297,\n    \"lng\": 111.0186,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 772113.0,\n    \"id\": 1156000460\n  },\n  {\n    \"city\": \"Yongji\",\n    \"city_ascii\": \"Yongji\",\n    \"lat\": 34.867,\n    \"lng\": 110.4417,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": null,\n    \"population\": 444724.0,\n    \"id\": 1156001205\n  },\n  {\n    \"city\": \"Xiaoganzhan\",\n    \"city_ascii\": \"Xiaoganzhan\",\n    \"lat\": 30.9273,\n    \"lng\": 113.911,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 4921000.0,\n    \"id\": 1156002290\n  },\n  {\n    \"city\": \"Lengshuijiang\",\n    \"city_ascii\": \"Lengshuijiang\",\n    \"lat\": 27.6858,\n    \"lng\": 111.4279,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 370300.0,\n    \"id\": 1156002852\n  },\n  {\n    \"city\": \"Liaocheng\",\n    \"city_ascii\": \"Liaocheng\",\n    \"lat\": 36.45,\n    \"lng\": 115.9833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 5952128.0,\n    \"id\": 1156006600\n  },\n  {\n    \"city\": \"Yatou\",\n    \"city_ascii\": \"Yatou\",\n    \"lat\": 37.1653,\n    \"lng\": 122.4867,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 714211.0,\n    \"id\": 1156009046\n  },\n  {\n    \"city\": \"Loudi\",\n    \"city_ascii\": \"Loudi\",\n    \"lat\": 27.7378,\n    \"lng\": 111.9974,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 3931800.0,\n    \"id\": 1156010654\n  },\n  {\n    \"city\": \"Changsha\",\n    \"city_ascii\": \"Changsha\",\n    \"lat\": 22.3762,\n    \"lng\": 112.6877,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 717700.0,\n    \"id\": 1156011120\n  },\n  {\n    \"city\": \"Yingcheng\",\n    \"city_ascii\": \"Yingcheng\",\n    \"lat\": 24.1878,\n    \"lng\": 113.4042,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 986400.0,\n    \"id\": 1156012356\n  },\n  {\n    \"city\": \"Longyan\",\n    \"city_ascii\": \"Longyan\",\n    \"lat\": 25.0881,\n    \"lng\": 117.0244,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 2723637.0,\n    \"id\": 1156012979\n  },\n  {\n    \"city\": \"Heshan\",\n    \"city_ascii\": \"Heshan\",\n    \"lat\": 22.7697,\n    \"lng\": 112.9578,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": null,\n    \"population\": 516500.0,\n    \"id\": 1156013872\n  },\n  {\n    \"city\": \"Wancheng\",\n    \"city_ascii\": \"Wancheng\",\n    \"lat\": 18.8,\n    \"lng\": 110.4,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hainan\",\n    \"capital\": \"minor\",\n    \"population\": 578600.0,\n    \"id\": 1156017483\n  },\n  {\n    \"city\": \"Kaihua\",\n    \"city_ascii\": \"Kaihua\",\n    \"lat\": 23.3715,\n    \"lng\": 104.2437,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": \"minor\",\n    \"population\": 481505.0,\n    \"id\": 1156017759\n  },\n  {\n    \"city\": \"Botou\",\n    \"city_ascii\": \"Botou\",\n    \"lat\": 38.074,\n    \"lng\": 116.57,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 584308.0,\n    \"id\": 1156018338\n  },\n  {\n    \"city\": \"Huadian\",\n    \"city_ascii\": \"Huadian\",\n    \"lat\": 42.9633,\n    \"lng\": 126.7478,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": null,\n    \"population\": 455339.0,\n    \"id\": 1156018839\n  },\n  {\n    \"city\": \"Bijie\",\n    \"city_ascii\": \"Bijie\",\n    \"lat\": 27.3019,\n    \"lng\": 105.2863,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": null,\n    \"population\": 6899636.0,\n    \"id\": 1156018927\n  },\n  {\n    \"city\": \"Wuxi\",\n    \"city_ascii\": \"Wuxi\",\n    \"lat\": 31.5667,\n    \"lng\": 120.2833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 3245179.0,\n    \"id\": 1156019650\n  },\n  {\n    \"city\": \"Lianzhou\",\n    \"city_ascii\": \"Lianzhou\",\n    \"lat\": 24.7868,\n    \"lng\": 112.3735,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 384700.0,\n    \"id\": 1156020454\n  },\n  {\n    \"city\": \"Meishan\",\n    \"city_ascii\": \"Meishan\",\n    \"lat\": 34.1736,\n    \"lng\": 112.839,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 936000.0,\n    \"id\": 1156023073\n  },\n  {\n    \"city\": \"Zigong\",\n    \"city_ascii\": \"Zigong\",\n    \"lat\": 29.3498,\n    \"lng\": 104.7645,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": null,\n    \"population\": 2678899.0,\n    \"id\": 1156023354\n  },\n  {\n    \"city\": \"Sanzhou\",\n    \"city_ascii\": \"Sanzhou\",\n    \"lat\": 30.82,\n    \"lng\": 108.4,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Chongqing\",\n    \"capital\": null,\n    \"population\": 1680000.0,\n    \"id\": 1156025536\n  },\n  {\n    \"city\": \"Wuxue\",\n    \"city_ascii\": \"Wuxue\",\n    \"lat\": 29.8518,\n    \"lng\": 115.5539,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"minor\",\n    \"population\": 644247.0,\n    \"id\": 1156027100\n  },\n  {\n    \"city\": \"Suzhou\",\n    \"city_ascii\": \"Suzhou\",\n    \"lat\": 31.3,\n    \"lng\": 120.6194,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 4330000.0,\n    \"id\": 1156029196\n  },\n  {\n    \"city\": \"Shanhu\",\n    \"city_ascii\": \"Shanhu\",\n    \"lat\": 29.5908,\n    \"lng\": 120.8176,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 679762.0,\n    \"id\": 1156029691\n  },\n  {\n    \"city\": \"Qinbaling\",\n    \"city_ascii\": \"Qinbaling\",\n    \"lat\": 35.7278,\n    \"lng\": 107.64,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": null,\n    \"population\": 2211191.0,\n    \"id\": 1156032582\n  },\n  {\n    \"city\": \"Baotou\",\n    \"city_ascii\": \"Baotou\",\n    \"lat\": 40.6562,\n    \"lng\": 109.8345,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Inner Mongolia\",\n    \"capital\": null,\n    \"population\": 2709378.0,\n    \"id\": 1156032751\n  },\n  {\n    \"city\": \"Rizhao\",\n    \"city_ascii\": \"Rizhao\",\n    \"lat\": 35.4164,\n    \"lng\": 119.4331,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 2968365.0,\n    \"id\": 1156032841\n  },\n  {\n    \"city\": \"Jingcheng\",\n    \"city_ascii\": \"Jingcheng\",\n    \"lat\": 32.0058,\n    \"lng\": 120.2547,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 684360.0,\n    \"id\": 1156033208\n  },\n  {\n    \"city\": \"Jiangyin\",\n    \"city_ascii\": \"Jiangyin\",\n    \"lat\": 31.9087,\n    \"lng\": 120.2653,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": null,\n    \"population\": 1285785.0,\n    \"id\": 1156033234\n  },\n  {\n    \"city\": \"Qingping\",\n    \"city_ascii\": \"Qingping\",\n    \"lat\": 34.538,\n    \"lng\": 113.3796,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 797200.0,\n    \"id\": 1156033855\n  },\n  {\n    \"city\": \"Longjiang\",\n    \"city_ascii\": \"Longjiang\",\n    \"lat\": 27.582,\n    \"lng\": 120.5488,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 464695.0,\n    \"id\": 1156034166\n  },\n  {\n    \"city\": \"Xinpu\",\n    \"city_ascii\": \"Xinpu\",\n    \"lat\": 34.5906,\n    \"lng\": 119.1801,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 4599360.0,\n    \"id\": 1156035381\n  },\n  {\n    \"city\": \"Huichang\",\n    \"city_ascii\": \"Huichang\",\n    \"lat\": 34.9136,\n    \"lng\": 112.7852,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 367113.0,\n    \"id\": 1156035769\n  },\n  {\n    \"city\": \"Chuzhou\",\n    \"city_ascii\": \"Chuzhou\",\n    \"lat\": 32.3062,\n    \"lng\": 118.3115,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": null,\n    \"population\": 3987054.0,\n    \"id\": 1156036420\n  },\n  {\n    \"city\": \"Jingdezhen\",\n    \"city_ascii\": \"Jingdezhen\",\n    \"lat\": 29.2942,\n    \"lng\": 117.2036,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": \"minor\",\n    \"population\": 1673200.0,\n    \"id\": 1156038165\n  },\n  {\n    \"city\": \"Hongjiang\",\n    \"city_ascii\": \"Hongjiang\",\n    \"lat\": 27.1167,\n    \"lng\": 109.95,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 498100.0,\n    \"id\": 1156039152\n  },\n  {\n    \"city\": \"Hengzhou\",\n    \"city_ascii\": \"Hengzhou\",\n    \"lat\": 22.6896,\n    \"lng\": 109.2674,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 908400.0,\n    \"id\": 1156041202\n  },\n  {\n    \"city\": \"Zhuzhou\",\n    \"city_ascii\": \"Zhuzhou\",\n    \"lat\": 27.8407,\n    \"lng\": 113.1469,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 4020800.0,\n    \"id\": 1156041962\n  },\n  {\n    \"city\": \"Linxia Chengguanzhen\",\n    \"city_ascii\": \"Linxia Chengguanzhen\",\n    \"lat\": 35.6,\n    \"lng\": 103.2167,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": \"minor\",\n    \"population\": 355968.0,\n    \"id\": 1156043522\n  },\n  {\n    \"city\": \"Leling\",\n    \"city_ascii\": \"Leling\",\n    \"lat\": 37.7333,\n    \"lng\": 117.2167,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 689867.0,\n    \"id\": 1156044041\n  },\n  {\n    \"city\": \"Lincang\",\n    \"city_ascii\": \"Lincang\",\n    \"lat\": 23.8864,\n    \"lng\": 100.0871,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": null,\n    \"population\": 2536000.0,\n    \"id\": 1156044130\n  },\n  {\n    \"city\": \"Zhuozhou\",\n    \"city_ascii\": \"Zhuozhou\",\n    \"lat\": 39.4887,\n    \"lng\": 115.9918,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 603535.0,\n    \"id\": 1156045160\n  },\n  {\n    \"city\": \"Nantong\",\n    \"city_ascii\": \"Nantong\",\n    \"lat\": 31.9829,\n    \"lng\": 120.8873,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 2261382.0,\n    \"id\": 1156045365\n  },\n  {\n    \"city\": \"Puxi\",\n    \"city_ascii\": \"Puxi\",\n    \"lat\": 35.2125,\n    \"lng\": 114.735,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 809535.0,\n    \"id\": 1156046618\n  },\n  {\n    \"city\": \"Lianshan\",\n    \"city_ascii\": \"Lianshan\",\n    \"lat\": 40.7523,\n    \"lng\": 120.828,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": \"minor\",\n    \"population\": 2426000.0,\n    \"id\": 1156046704\n  },\n  {\n    \"city\": \"Xushan\",\n    \"city_ascii\": \"Xushan\",\n    \"lat\": 30.1697,\n    \"lng\": 121.2665,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 1502000.0,\n    \"id\": 1156046916\n  },\n  {\n    \"city\": \"Yan’an Beilu\",\n    \"city_ascii\": \"Yan'an Beilu\",\n    \"lat\": 44.0144,\n    \"lng\": 87.2674,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"minor\",\n    \"population\": 426253.0,\n    \"id\": 1156048097\n  },\n  {\n    \"city\": \"Ürümqi\",\n    \"city_ascii\": \"Urumqi\",\n    \"lat\": 43.8225,\n    \"lng\": 87.6125,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"admin\",\n    \"population\": 4335017.0,\n    \"id\": 1156051276\n  },\n  {\n    \"city\": \"Shuyangzha\",\n    \"city_ascii\": \"Shuyangzha\",\n    \"lat\": 34.1299,\n    \"lng\": 118.7734,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": null,\n    \"population\": 1770000.0,\n    \"id\": 1156051957\n  },\n  {\n    \"city\": \"Wenling\",\n    \"city_ascii\": \"Wenling\",\n    \"lat\": 28.3797,\n    \"lng\": 121.3718,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 1416199.0,\n    \"id\": 1156052493\n  },\n  {\n    \"city\": \"Haicheng\",\n    \"city_ascii\": \"Haicheng\",\n    \"lat\": 40.8523,\n    \"lng\": 122.7474,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": \"minor\",\n    \"population\": 1293877.0,\n    \"id\": 1156052713\n  },\n  {\n    \"city\": \"Yunfu\",\n    \"city_ascii\": \"Yunfu\",\n    \"lat\": 22.9242,\n    \"lng\": 112.0353,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 2526900.0,\n    \"id\": 1156057251\n  },\n  {\n    \"city\": \"Leiyang\",\n    \"city_ascii\": \"Leiyang\",\n    \"lat\": 26.4179,\n    \"lng\": 112.8457,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 1151554.0,\n    \"id\": 1156057789\n  },\n  {\n    \"city\": \"Changzhi\",\n    \"city_ascii\": \"Changzhi\",\n    \"lat\": 36.1953,\n    \"lng\": 113.097,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": \"minor\",\n    \"population\": 3334565.0,\n    \"id\": 1156057944\n  },\n  {\n    \"city\": \"Dunhua\",\n    \"city_ascii\": \"Dunhua\",\n    \"lat\": 43.3667,\n    \"lng\": 128.2333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 483811.0,\n    \"id\": 1156058709\n  },\n  {\n    \"city\": \"Wudalianchi\",\n    \"city_ascii\": \"Wudalianchi\",\n    \"lat\": 48.6433,\n    \"lng\": 126.1408,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 360000.0,\n    \"id\": 1156059331\n  },\n  {\n    \"city\": \"Jingling\",\n    \"city_ascii\": \"Jingling\",\n    \"lat\": 30.6667,\n    \"lng\": 113.1667,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 1247400.0,\n    \"id\": 1156060544\n  },\n  {\n    \"city\": \"Siping\",\n    \"city_ascii\": \"Siping\",\n    \"lat\": 43.1715,\n    \"lng\": 124.3644,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 3385156.0,\n    \"id\": 1156063295\n  },\n  {\n    \"city\": \"Ghulja\",\n    \"city_ascii\": \"Ghulja\",\n    \"lat\": 43.9,\n    \"lng\": 81.35,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"minor\",\n    \"population\": 542507.0,\n    \"id\": 1156064979\n  },\n  {\n    \"city\": \"Pingxiang\",\n    \"city_ascii\": \"Pingxiang\",\n    \"lat\": 27.6333,\n    \"lng\": 113.85,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": \"minor\",\n    \"population\": 1933200.0,\n    \"id\": 1156066465\n  },\n  {\n    \"city\": \"Luoyang\",\n    \"city_ascii\": \"Luoyang\",\n    \"lat\": 34.6587,\n    \"lng\": 112.4245,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 2372571.0,\n    \"id\": 1156069315\n  },\n  {\n    \"city\": \"Zhangjiajie\",\n    \"city_ascii\": \"Zhangjiajie\",\n    \"lat\": 29.1255,\n    \"lng\": 110.4844,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 1537900.0,\n    \"id\": 1156072884\n  },\n  {\n    \"city\": \"Shanghai\",\n    \"city_ascii\": \"Shanghai\",\n    \"lat\": 31.1667,\n    \"lng\": 121.4667,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanghai\",\n    \"capital\": \"admin\",\n    \"population\": 24073000.0,\n    \"id\": 1156073548\n  },\n  {\n    \"city\": \"Shishi\",\n    \"city_ascii\": \"Shishi\",\n    \"lat\": 24.7355,\n    \"lng\": 118.6434,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 693000.0,\n    \"id\": 1156077046\n  },\n  {\n    \"city\": \"Zhugang\",\n    \"city_ascii\": \"Zhugang\",\n    \"lat\": 28.1277,\n    \"lng\": 121.2288,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 616346.0,\n    \"id\": 1156077330\n  },\n  {\n    \"city\": \"Yiwu\",\n    \"city_ascii\": \"Yiwu\",\n    \"lat\": 29.3081,\n    \"lng\": 120.0698,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 1234015.0,\n    \"id\": 1156078044\n  },\n  {\n    \"city\": \"Changchun\",\n    \"city_ascii\": \"Changchun\",\n    \"lat\": 43.9,\n    \"lng\": 125.2,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"admin\",\n    \"population\": 4408154.0,\n    \"id\": 1156078103\n  },\n  {\n    \"city\": \"Xiashi\",\n    \"city_ascii\": \"Xiashi\",\n    \"lat\": 30.5333,\n    \"lng\": 120.6833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 1076199.0,\n    \"id\": 1156080077\n  },\n  {\n    \"city\": \"Linghai\",\n    \"city_ascii\": \"Linghai\",\n    \"lat\": 41.1676,\n    \"lng\": 121.3558,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 412513.0,\n    \"id\": 1156081300\n  },\n  {\n    \"city\": \"Xining\",\n    \"city_ascii\": \"Xining\",\n    \"lat\": 36.6239,\n    \"lng\": 101.7787,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Qinghai\",\n    \"capital\": \"admin\",\n    \"population\": 2467965.0,\n    \"id\": 1156081448\n  },\n  {\n    \"city\": \"Kaiyuan\",\n    \"city_ascii\": \"Kaiyuan\",\n    \"lat\": 42.538,\n    \"lng\": 124.0371,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 545624.0,\n    \"id\": 1156081841\n  },\n  {\n    \"city\": \"Beian\",\n    \"city_ascii\": \"Beian\",\n    \"lat\": 48.2395,\n    \"lng\": 126.5037,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 470000.0,\n    \"id\": 1156084414\n  },\n  {\n    \"city\": \"Guangyuan\",\n    \"city_ascii\": \"Guangyuan\",\n    \"lat\": 32.4353,\n    \"lng\": 105.8398,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": null,\n    \"population\": 2484122.0,\n    \"id\": 1156084562\n  },\n  {\n    \"city\": \"Duyun\",\n    \"city_ascii\": \"Duyun\",\n    \"lat\": 26.2672,\n    \"lng\": 107.5143,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": null,\n    \"population\": 493574.0,\n    \"id\": 1156084618\n  },\n  {\n    \"city\": \"Linyi\",\n    \"city_ascii\": \"Linyi\",\n    \"lat\": 35.1041,\n    \"lng\": 118.3502,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 11018365.0,\n    \"id\": 1156086320\n  },\n  {\n    \"city\": \"Zijinglu\",\n    \"city_ascii\": \"Zijinglu\",\n    \"lat\": 34.7513,\n    \"lng\": 112.9854,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 807857.0,\n    \"id\": 1156086381\n  },\n  {\n    \"city\": \"Wugang\",\n    \"city_ascii\": \"Wugang\",\n    \"lat\": 26.7345,\n    \"lng\": 110.6293,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 734870.0,\n    \"id\": 1156089788\n  },\n  {\n    \"city\": \"Tieling\",\n    \"city_ascii\": \"Tieling\",\n    \"lat\": 42.2841,\n    \"lng\": 123.8365,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 2717732.0,\n    \"id\": 1156089994\n  },\n  {\n    \"city\": \"Qinhuangdao\",\n    \"city_ascii\": \"Qinhuangdao\",\n    \"lat\": 39.9398,\n    \"lng\": 119.5881,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 3146300.0,\n    \"id\": 1156091093\n  },\n  {\n    \"city\": \"Shangzhou\",\n    \"city_ascii\": \"Shangzhou\",\n    \"lat\": 33.868,\n    \"lng\": 109.9244,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": null,\n    \"population\": 2341742.0,\n    \"id\": 1156091241\n  },\n  {\n    \"city\": \"Luanzhou\",\n    \"city_ascii\": \"Luanzhou\",\n    \"lat\": 39.7396,\n    \"lng\": 118.6978,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": \"minor\",\n    \"population\": 554315.0,\n    \"id\": 1156092104\n  },\n  {\n    \"city\": \"Tai’an\",\n    \"city_ascii\": \"Tai'an\",\n    \"lat\": 36.2001,\n    \"lng\": 117.0809,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 5494207.0,\n    \"id\": 1156095188\n  },\n  {\n    \"city\": \"Dengtacun\",\n    \"city_ascii\": \"Dengtacun\",\n    \"lat\": 41.4237,\n    \"lng\": 123.3203,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 496122.0,\n    \"id\": 1156096868\n  },\n  {\n    \"city\": \"Benxi\",\n    \"city_ascii\": \"Benxi\",\n    \"lat\": 41.292,\n    \"lng\": 123.761,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 1709538.0,\n    \"id\": 1156097909\n  },\n  {\n    \"city\": \"Baojishi\",\n    \"city_ascii\": \"Baojishi\",\n    \"lat\": 34.3609,\n    \"lng\": 107.1751,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": null,\n    \"population\": 3738700.0,\n    \"id\": 1156101096\n  },\n  {\n    \"city\": \"Rongcheng\",\n    \"city_ascii\": \"Rongcheng\",\n    \"lat\": 29.8239,\n    \"lng\": 112.9019,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"minor\",\n    \"population\": 1162770.0,\n    \"id\": 1156102432\n  },\n  {\n    \"city\": \"Puyang Chengguanzhen\",\n    \"city_ascii\": \"Puyang Chengguanzhen\",\n    \"lat\": 35.7004,\n    \"lng\": 114.98,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 666322.0,\n    \"id\": 1156103317\n  },\n  {\n    \"city\": \"Qincheng\",\n    \"city_ascii\": \"Qincheng\",\n    \"lat\": 34.5809,\n    \"lng\": 105.7311,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": \"minor\",\n    \"population\": 3262549.0,\n    \"id\": 1156104017\n  },\n  {\n    \"city\": \"Ruiming\",\n    \"city_ascii\": \"Ruiming\",\n    \"lat\": 25.8833,\n    \"lng\": 116.0333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": null,\n    \"population\": 640600.0,\n    \"id\": 1156104573\n  },\n  {\n    \"city\": \"Taishan\",\n    \"city_ascii\": \"Taishan\",\n    \"lat\": 22.2486,\n    \"lng\": 112.785,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": null,\n    \"population\": 953900.0,\n    \"id\": 1156105450\n  },\n  {\n    \"city\": \"Jiangmen\",\n    \"city_ascii\": \"Jiangmen\",\n    \"lat\": 22.5833,\n    \"lng\": 113.0833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 4630300.0,\n    \"id\": 1156105613\n  },\n  {\n    \"city\": \"Kuaidamao\",\n    \"city_ascii\": \"Kuaidamao\",\n    \"lat\": 41.7302,\n    \"lng\": 125.9471,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 2324439.0,\n    \"id\": 1156106507\n  },\n  {\n    \"city\": \"Qinzhou\",\n    \"city_ascii\": \"Qinzhou\",\n    \"lat\": 21.95,\n    \"lng\": 108.6167,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 3304400.0,\n    \"id\": 1156106602\n  },\n  {\n    \"city\": \"Xigazê\",\n    \"city_ascii\": \"Xigaze\",\n    \"lat\": 29.25,\n    \"lng\": 88.8833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Tibet\",\n    \"capital\": \"minor\",\n    \"population\": 798153.0,\n    \"id\": 1156107208\n  },\n  {\n    \"city\": \"Xiangyang\",\n    \"city_ascii\": \"Xiangyang\",\n    \"lat\": 32.0654,\n    \"lng\": 112.1531,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"minor\",\n    \"population\": 5680000.0,\n    \"id\": 1156107325\n  },\n  {\n    \"city\": \"Shangzhi\",\n    \"city_ascii\": \"Shangzhi\",\n    \"lat\": 45.2116,\n    \"lng\": 127.962,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 585386.0,\n    \"id\": 1156107332\n  },\n  {\n    \"city\": \"Yibin\",\n    \"city_ascii\": \"Yibin\",\n    \"lat\": 28.7596,\n    \"lng\": 104.64,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 4588804.0,\n    \"id\": 1156107603\n  },\n  {\n    \"city\": \"Langfang\",\n    \"city_ascii\": \"Langfang\",\n    \"lat\": 39.5196,\n    \"lng\": 116.7006,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 5464087.0,\n    \"id\": 1156109017\n  },\n  {\n    \"city\": \"Qingdao\",\n    \"city_ascii\": \"Qingdao\",\n    \"lat\": 36.1167,\n    \"lng\": 120.4,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 5818255.0,\n    \"id\": 1156112588\n  },\n  {\n    \"city\": \"Kashgar\",\n    \"city_ascii\": \"Kashgar\",\n    \"lat\": 39.4681,\n    \"lng\": 75.9938,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"minor\",\n    \"population\": 920000.0,\n    \"id\": 1156113193\n  },\n  {\n    \"city\": \"Pizhou\",\n    \"city_ascii\": \"Pizhou\",\n    \"lat\": 34.3422,\n    \"lng\": 118.0097,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": null,\n    \"population\": 1458038.0,\n    \"id\": 1156114238\n  },\n  {\n    \"city\": \"Hebi\",\n    \"city_ascii\": \"Hebi\",\n    \"lat\": 35.7497,\n    \"lng\": 114.2887,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 1569208.0,\n    \"id\": 1156114258\n  },\n  {\n    \"city\": \"Xichang\",\n    \"city_ascii\": \"Xichang\",\n    \"lat\": 27.8983,\n    \"lng\": 102.2706,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 712434.0,\n    \"id\": 1156116456\n  },\n  {\n    \"city\": \"Wuhan\",\n    \"city_ascii\": \"Wuhan\",\n    \"lat\": 30.5872,\n    \"lng\": 114.2881,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"admin\",\n    \"population\": 10251000.0,\n    \"id\": 1156117184\n  },\n  {\n    \"city\": \"Taizhou\",\n    \"city_ascii\": \"Taizhou\",\n    \"lat\": 32.4831,\n    \"lng\": 119.9,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 5031000.0,\n    \"id\": 1156119229\n  },\n  {\n    \"city\": \"Xianyang\",\n    \"city_ascii\": \"Xianyang\",\n    \"lat\": 34.35,\n    \"lng\": 108.7167,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": \"minor\",\n    \"population\": 5096001.0,\n    \"id\": 1156120117\n  },\n  {\n    \"city\": \"Rongcheng\",\n    \"city_ascii\": \"Rongcheng\",\n    \"lat\": 26.2312,\n    \"lng\": 104.0966,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": null,\n    \"population\": 1302891.0,\n    \"id\": 1156122888\n  },\n  {\n    \"city\": \"Yangjiang\",\n    \"city_ascii\": \"Yangjiang\",\n    \"lat\": 21.8556,\n    \"lng\": 111.9627,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 2555600.0,\n    \"id\": 1156123172\n  },\n  {\n    \"city\": \"Deyang\",\n    \"city_ascii\": \"Deyang\",\n    \"lat\": 31.1289,\n    \"lng\": 104.395,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 3877000.0,\n    \"id\": 1156127147\n  },\n  {\n    \"city\": \"Bazhou\",\n    \"city_ascii\": \"Bazhou\",\n    \"lat\": 39.1235,\n    \"lng\": 116.386,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 622975.0,\n    \"id\": 1156127276\n  },\n  {\n    \"city\": \"Nangandao\",\n    \"city_ascii\": \"Nangandao\",\n    \"lat\": 35.2992,\n    \"lng\": 113.8851,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 5708191.0,\n    \"id\": 1156127660\n  },\n  {\n    \"city\": \"Huanghua\",\n    \"city_ascii\": \"Huanghua\",\n    \"lat\": 38.371,\n    \"lng\": 117.3329,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": \"minor\",\n    \"population\": 548507.0,\n    \"id\": 1156131099\n  },\n  {\n    \"city\": \"Chizhou\",\n    \"city_ascii\": \"Chizhou\",\n    \"lat\": 30.6583,\n    \"lng\": 117.4849,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 1402518.0,\n    \"id\": 1156131504\n  },\n  {\n    \"city\": \"Kumul\",\n    \"city_ascii\": \"Kumul\",\n    \"lat\": 42.8193,\n    \"lng\": 93.5151,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"minor\",\n    \"population\": 673383.0,\n    \"id\": 1156131545\n  },\n  {\n    \"city\": \"Qingyuan\",\n    \"city_ascii\": \"Qingyuan\",\n    \"lat\": 23.6842,\n    \"lng\": 113.0507,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 3969473.0,\n    \"id\": 1156135890\n  },\n  {\n    \"city\": \"Meicheng\",\n    \"city_ascii\": \"Meicheng\",\n    \"lat\": 30.6412,\n    \"lng\": 116.5689,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 500292.0,\n    \"id\": 1156136207\n  },\n  {\n    \"city\": \"Beidao\",\n    \"city_ascii\": \"Beidao\",\n    \"lat\": 34.602,\n    \"lng\": 105.918,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": \"minor\",\n    \"population\": 1225000.0,\n    \"id\": 1156137209\n  },\n  {\n    \"city\": \"Xinyu\",\n    \"city_ascii\": \"Xinyu\",\n    \"lat\": 27.795,\n    \"lng\": 114.9242,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": \"minor\",\n    \"population\": 1202499.0,\n    \"id\": 1156138735\n  },\n  {\n    \"city\": \"Luocheng\",\n    \"city_ascii\": \"Luocheng\",\n    \"lat\": 22.7645,\n    \"lng\": 111.5745,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 984100.0,\n    \"id\": 1156138895\n  },\n  {\n    \"city\": \"Wuzhong\",\n    \"city_ascii\": \"Wuzhong\",\n    \"lat\": 37.9874,\n    \"lng\": 106.1919,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Ningxia\",\n    \"capital\": \"minor\",\n    \"population\": 1382713.0,\n    \"id\": 1156139322\n  },\n  {\n    \"city\": \"Chang’an\",\n    \"city_ascii\": \"Chang'an\",\n    \"lat\": 29.4761,\n    \"lng\": 113.448,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 537500.0,\n    \"id\": 1156139784\n  },\n  {\n    \"city\": \"Baiyin\",\n    \"city_ascii\": \"Baiyin\",\n    \"lat\": 36.5448,\n    \"lng\": 104.1766,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": \"minor\",\n    \"population\": 1708751.0,\n    \"id\": 1156140738\n  },\n  {\n    \"city\": \"Fuxin\",\n    \"city_ascii\": \"Fuxin\",\n    \"lat\": 42.0127,\n    \"lng\": 121.6486,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 1819339.0,\n    \"id\": 1156141954\n  },\n  {\n    \"city\": \"Dashiqiao\",\n    \"city_ascii\": \"Dashiqiao\",\n    \"lat\": 40.6328,\n    \"lng\": 122.5021,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": \"minor\",\n    \"population\": 704891.0,\n    \"id\": 1156141962\n  },\n  {\n    \"city\": \"Anda\",\n    \"city_ascii\": \"Anda\",\n    \"lat\": 46.4078,\n    \"lng\": 125.3252,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 520000.0,\n    \"id\": 1156142150\n  },\n  {\n    \"city\": \"Yiyang\",\n    \"city_ascii\": \"Yiyang\",\n    \"lat\": 26.4103,\n    \"lng\": 112.3913,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 810447.0,\n    \"id\": 1156142520\n  },\n  {\n    \"city\": \"Huaibei\",\n    \"city_ascii\": \"Huaibei\",\n    \"lat\": 33.9562,\n    \"lng\": 116.789,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": null,\n    \"population\": 2114276.0,\n    \"id\": 1156142626\n  },\n  {\n    \"city\": \"Songyang\",\n    \"city_ascii\": \"Songyang\",\n    \"lat\": 34.4603,\n    \"lng\": 113.028,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 668592.0,\n    \"id\": 1156143149\n  },\n  {\n    \"city\": \"Gaizhou\",\n    \"city_ascii\": \"Gaizhou\",\n    \"lat\": 40.4019,\n    \"lng\": 122.3499,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": \"minor\",\n    \"population\": 691595.0,\n    \"id\": 1156145272\n  },\n  {\n    \"city\": \"Pencheng\",\n    \"city_ascii\": \"Pencheng\",\n    \"lat\": 29.6792,\n    \"lng\": 115.6611,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": null,\n    \"population\": 419047.0,\n    \"id\": 1156147187\n  },\n  {\n    \"city\": \"Hanchuan\",\n    \"city_ascii\": \"Hanchuan\",\n    \"lat\": 30.652,\n    \"lng\": 113.8274,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 1092700.0,\n    \"id\": 1156149248\n  },\n  {\n    \"city\": \"Huili Chengguanzhen\",\n    \"city_ascii\": \"Huili Chengguanzhen\",\n    \"lat\": 26.6614,\n    \"lng\": 102.2469,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 430066.0,\n    \"id\": 1156149320\n  },\n  {\n    \"city\": \"Jiannan\",\n    \"city_ascii\": \"Jiannan\",\n    \"lat\": 31.3446,\n    \"lng\": 104.1994,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 477868.0,\n    \"id\": 1156155414\n  },\n  {\n    \"city\": \"Xishan\",\n    \"city_ascii\": \"Xishan\",\n    \"lat\": 27.6609,\n    \"lng\": 113.4946,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 1060000.0,\n    \"id\": 1156155575\n  },\n  {\n    \"city\": \"Pingdu\",\n    \"city_ascii\": \"Pingdu\",\n    \"lat\": 36.7833,\n    \"lng\": 119.9556,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 1378900.0,\n    \"id\": 1156157078\n  },\n  {\n    \"city\": \"Jinzhou\",\n    \"city_ascii\": \"Jinzhou\",\n    \"lat\": 41.1144,\n    \"lng\": 121.1292,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 3126463.0,\n    \"id\": 1156157151\n  },\n  {\n    \"city\": \"Yangquan\",\n    \"city_ascii\": \"Yangquan\",\n    \"lat\": 37.8576,\n    \"lng\": 113.5762,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": \"minor\",\n    \"population\": 1368502.0,\n    \"id\": 1156157844\n  },\n  {\n    \"city\": \"Jiaozuo\",\n    \"city_ascii\": \"Jiaozuo\",\n    \"lat\": 35.229,\n    \"lng\": 113.2304,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 3590700.0,\n    \"id\": 1156157854\n  },\n  {\n    \"city\": \"Luofeng\",\n    \"city_ascii\": \"Luofeng\",\n    \"lat\": 37.359,\n    \"lng\": 120.396,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 570898.0,\n    \"id\": 1156158643\n  },\n  {\n    \"city\": \"Shenzhen\",\n    \"city_ascii\": \"Shenzhen\",\n    \"lat\": 22.535,\n    \"lng\": 114.054,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 17619000.0,\n    \"id\": 1156158707\n  },\n  {\n    \"city\": \"Xicheng\",\n    \"city_ascii\": \"Xicheng\",\n    \"lat\": 23.3629,\n    \"lng\": 103.1545,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": \"minor\",\n    \"population\": 459781.0,\n    \"id\": 1156161838\n  },\n  {\n    \"city\": \"Jincheng\",\n    \"city_ascii\": \"Jincheng\",\n    \"lat\": 35.4906,\n    \"lng\": 112.8483,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": \"minor\",\n    \"population\": 2279146.0,\n    \"id\": 1156163376\n  },\n  {\n    \"city\": \"Guiping\",\n    \"city_ascii\": \"Guiping\",\n    \"lat\": 23.4,\n    \"lng\": 110.0833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 1511011.0,\n    \"id\": 1156165517\n  },\n  {\n    \"city\": \"Changping\",\n    \"city_ascii\": \"Changping\",\n    \"lat\": 40.2248,\n    \"lng\": 116.1944,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Beijing\",\n    \"capital\": null,\n    \"population\": 614821.0,\n    \"id\": 1156166828\n  },\n  {\n    \"city\": \"Hechi\",\n    \"city_ascii\": \"Hechi\",\n    \"lat\": 24.6928,\n    \"lng\": 108.085,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 3545700.0,\n    \"id\": 1156167204\n  },\n  {\n    \"city\": \"Zhaoqing\",\n    \"city_ascii\": \"Zhaoqing\",\n    \"lat\": 23.05,\n    \"lng\": 112.4667,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 4151700.0,\n    \"id\": 1156170144\n  },\n  {\n    \"city\": \"Ningbo\",\n    \"city_ascii\": \"Ningbo\",\n    \"lat\": 29.875,\n    \"lng\": 121.5492,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 4087523.0,\n    \"id\": 1156170787\n  },\n  {\n    \"city\": \"Anguo\",\n    \"city_ascii\": \"Anguo\",\n    \"lat\": 38.4177,\n    \"lng\": 115.3204,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 370317.0,\n    \"id\": 1156172518\n  },\n  {\n    \"city\": \"Ximeicun\",\n    \"city_ascii\": \"Ximeicun\",\n    \"lat\": 24.9633,\n    \"lng\": 118.3811,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": null,\n    \"population\": 1508000.0,\n    \"id\": 1156173813\n  },\n  {\n    \"city\": \"Tianjin\",\n    \"city_ascii\": \"Tianjin\",\n    \"lat\": 39.1467,\n    \"lng\": 117.2056,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Tianjin\",\n    \"capital\": \"admin\",\n    \"population\": 10368000.0,\n    \"id\": 1156174046\n  },\n  {\n    \"city\": \"Kuiju\",\n    \"city_ascii\": \"Kuiju\",\n    \"lat\": 36.8528,\n    \"lng\": 119.3904,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 564501.0,\n    \"id\": 1156174997\n  },\n  {\n    \"city\": \"Dalian\",\n    \"city_ascii\": \"Dalian\",\n    \"lat\": 38.9,\n    \"lng\": 121.6,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 5871474.0,\n    \"id\": 1156175472\n  },\n  {\n    \"city\": \"Yuci\",\n    \"city_ascii\": \"Yuci\",\n    \"lat\": 37.6823,\n    \"lng\": 112.7281,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": null,\n    \"population\": 840000.0,\n    \"id\": 1156177817\n  },\n  {\n    \"city\": \"Dandong\",\n    \"city_ascii\": \"Dandong\",\n    \"lat\": 40.1167,\n    \"lng\": 124.3833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 2444697.0,\n    \"id\": 1156178316\n  },\n  {\n    \"city\": \"Zhangye\",\n    \"city_ascii\": \"Zhangye\",\n    \"lat\": 38.9355,\n    \"lng\": 100.4553,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": \"minor\",\n    \"population\": 1199515.0,\n    \"id\": 1156180353\n  },\n  {\n    \"city\": \"Quzhou\",\n    \"city_ascii\": \"Quzhou\",\n    \"lat\": 28.9545,\n    \"lng\": 118.8763,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 902767.0,\n    \"id\": 1156180376\n  },\n  {\n    \"city\": \"Luocheng\",\n    \"city_ascii\": \"Luocheng\",\n    \"lat\": 30.9793,\n    \"lng\": 104.28,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 591115.0,\n    \"id\": 1156180482\n  },\n  {\n    \"city\": \"Jinghong\",\n    \"city_ascii\": \"Jinghong\",\n    \"lat\": 22.0057,\n    \"lng\": 100.7948,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": null,\n    \"population\": 519935.0,\n    \"id\": 1156181533\n  },\n  {\n    \"city\": \"Wutong\",\n    \"city_ascii\": \"Wutong\",\n    \"lat\": 30.6326,\n    \"lng\": 120.5474,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 1029754.0,\n    \"id\": 1156182309\n  },\n  {\n    \"city\": \"Zhengzhou\",\n    \"city_ascii\": \"Zhengzhou\",\n    \"lat\": 34.7492,\n    \"lng\": 113.6605,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"admin\",\n    \"population\": 5621593.0,\n    \"id\": 1156183137\n  },\n  {\n    \"city\": \"Haikou\",\n    \"city_ascii\": \"Haikou\",\n    \"lat\": 20.02,\n    \"lng\": 110.32,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hainan\",\n    \"capital\": \"admin\",\n    \"population\": 2873358.0,\n    \"id\": 1156183327\n  },\n  {\n    \"city\": \"Lingyuan\",\n    \"city_ascii\": \"Lingyuan\",\n    \"lat\": 41.2407,\n    \"lng\": 119.3957,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 570660.0,\n    \"id\": 1156184681\n  },\n  {\n    \"city\": \"Zhumadian\",\n    \"city_ascii\": \"Zhumadian\",\n    \"lat\": 32.9773,\n    \"lng\": 114.0253,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 7231234.0,\n    \"id\": 1156184822\n  },\n  {\n    \"city\": \"Jinchang\",\n    \"city_ascii\": \"Jinchang\",\n    \"lat\": 38.5168,\n    \"lng\": 102.1866,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": \"minor\",\n    \"population\": 438026.0,\n    \"id\": 1156184861\n  },\n  {\n    \"city\": \"Yong’an\",\n    \"city_ascii\": \"Yong'an\",\n    \"lat\": 25.9733,\n    \"lng\": 117.3593,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 357000.0,\n    \"id\": 1156185328\n  },\n  {\n    \"city\": \"Meishan\",\n    \"city_ascii\": \"Meishan\",\n    \"lat\": 30.0575,\n    \"lng\": 103.8381,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": null,\n    \"population\": 2950545.0,\n    \"id\": 1156185501\n  },\n  {\n    \"city\": \"Changzhou\",\n    \"city_ascii\": \"Changzhou\",\n    \"lat\": 31.8122,\n    \"lng\": 119.9692,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 3601079.0,\n    \"id\": 1156185511\n  },\n  {\n    \"city\": \"Fuzhou\",\n    \"city_ascii\": \"Fuzhou\",\n    \"lat\": 26.0769,\n    \"lng\": 119.2917,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"admin\",\n    \"population\": 3671192.0,\n    \"id\": 1156188037\n  },\n  {\n    \"city\": \"Wenzhou\",\n    \"city_ascii\": \"Wenzhou\",\n    \"lat\": 27.9991,\n    \"lng\": 120.6561,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 3604446.0,\n    \"id\": 1156188829\n  },\n  {\n    \"city\": \"Nanyang\",\n    \"city_ascii\": \"Nanyang\",\n    \"lat\": 32.9987,\n    \"lng\": 112.5292,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 10013600.0,\n    \"id\": 1156192287\n  },\n  {\n    \"city\": \"Weichanglu\",\n    \"city_ascii\": \"Weichanglu\",\n    \"lat\": 37.1792,\n    \"lng\": 119.9333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 859424.0,\n    \"id\": 1156194600\n  },\n  {\n    \"city\": \"Xiangtan\",\n    \"city_ascii\": \"Xiangtan\",\n    \"lat\": 27.8431,\n    \"lng\": 112.9228,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 2864800.0,\n    \"id\": 1156195684\n  },\n  {\n    \"city\": \"Fuyuan\",\n    \"city_ascii\": \"Fuyuan\",\n    \"lat\": 48.3614,\n    \"lng\": 134.2875,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 480000.0,\n    \"id\": 1156196485\n  },\n  {\n    \"city\": \"Zaoyang\",\n    \"city_ascii\": \"Zaoyang\",\n    \"lat\": 32.1287,\n    \"lng\": 112.7581,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 1004741.0,\n    \"id\": 1156197076\n  },\n  {\n    \"city\": \"Wuchuan\",\n    \"city_ascii\": \"Wuchuan\",\n    \"lat\": 21.4283,\n    \"lng\": 110.7749,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": null,\n    \"population\": 972400.0,\n    \"id\": 1156198103\n  },\n  {\n    \"city\": \"Huanglongsi\",\n    \"city_ascii\": \"Huanglongsi\",\n    \"lat\": 34.795,\n    \"lng\": 114.345,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 4824016.0,\n    \"id\": 1156198356\n  },\n  {\n    \"city\": \"Nanchang\",\n    \"city_ascii\": \"Nanchang\",\n    \"lat\": 28.6842,\n    \"lng\": 115.8872,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": \"admin\",\n    \"population\": 3576547.0,\n    \"id\": 1156198892\n  },\n  {\n    \"city\": \"Huanggang\",\n    \"city_ascii\": \"Huanggang\",\n    \"lat\": 30.45,\n    \"lng\": 114.875,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"minor\",\n    \"population\": 6333000.0,\n    \"id\": 1156200037\n  },\n  {\n    \"city\": \"Zhoushan\",\n    \"city_ascii\": \"Zhoushan\",\n    \"lat\": 29.9887,\n    \"lng\": 122.2049,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 882932.0,\n    \"id\": 1156200283\n  },\n  {\n    \"city\": \"Dengtalu\",\n    \"city_ascii\": \"Dengtalu\",\n    \"lat\": 36.1386,\n    \"lng\": 114.1066,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 887000.0,\n    \"id\": 1156202014\n  },\n  {\n    \"city\": \"Lingcheng\",\n    \"city_ascii\": \"Lingcheng\",\n    \"lat\": 22.7,\n    \"lng\": 110.35,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": null,\n    \"population\": 1211637.0,\n    \"id\": 1156202191\n  },\n  {\n    \"city\": \"Liaoyang\",\n    \"city_ascii\": \"Liaoyang\",\n    \"lat\": 41.2643,\n    \"lng\": 123.1772,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 1858768.0,\n    \"id\": 1156202749\n  },\n  {\n    \"city\": \"Yangshe\",\n    \"city_ascii\": \"Yangshe\",\n    \"lat\": 31.8775,\n    \"lng\": 120.5512,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 1432044.0,\n    \"id\": 1156203000\n  },\n  {\n    \"city\": \"Leshan\",\n    \"city_ascii\": \"Leshan\",\n    \"lat\": 29.5854,\n    \"lng\": 103.7575,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": null,\n    \"population\": 3235759.0,\n    \"id\": 1156203130\n  },\n  {\n    \"city\": \"Huizhou\",\n    \"city_ascii\": \"Huizhou\",\n    \"lat\": 23.1115,\n    \"lng\": 114.4152,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 2509243.0,\n    \"id\": 1156203268\n  },\n  {\n    \"city\": \"Jiujiang\",\n    \"city_ascii\": \"Jiujiang\",\n    \"lat\": 29.7048,\n    \"lng\": 116.0021,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": \"minor\",\n    \"population\": 4896800.0,\n    \"id\": 1156206041\n  },\n  {\n    \"city\": \"Laiyang\",\n    \"city_ascii\": \"Laiyang\",\n    \"lat\": 36.9758,\n    \"lng\": 120.7136,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 874127.0,\n    \"id\": 1156207330\n  },\n  {\n    \"city\": \"Laiwu\",\n    \"city_ascii\": \"Laiwu\",\n    \"lat\": 36.1833,\n    \"lng\": 117.6667,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 1248636.0,\n    \"id\": 1156207332\n  },\n  {\n    \"city\": \"Xiping\",\n    \"city_ascii\": \"Xiping\",\n    \"lat\": 25.6005,\n    \"lng\": 103.8166,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": \"minor\",\n    \"population\": 652604.0,\n    \"id\": 1156207794\n  },\n  {\n    \"city\": \"Licheng\",\n    \"city_ascii\": \"Licheng\",\n    \"lat\": 24.4935,\n    \"lng\": 110.3902,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 352472.0,\n    \"id\": 1156208986\n  },\n  {\n    \"city\": \"Hohhot\",\n    \"city_ascii\": \"Hohhot\",\n    \"lat\": 40.8151,\n    \"lng\": 111.6629,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Inner Mongolia\",\n    \"capital\": \"admin\",\n    \"population\": 3446100.0,\n    \"id\": 1156210167\n  },\n  {\n    \"city\": \"Suqian\",\n    \"city_ascii\": \"Suqian\",\n    \"lat\": 33.9331,\n    \"lng\": 118.2831,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": null,\n    \"population\": 4986192.0,\n    \"id\": 1156212349\n  },\n  {\n    \"city\": \"Xiamen\",\n    \"city_ascii\": \"Xiamen\",\n    \"lat\": 24.4797,\n    \"lng\": 118.0819,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 3707090.0,\n    \"id\": 1156212809\n  },\n  {\n    \"city\": \"Xiangyang\",\n    \"city_ascii\": \"Xiangyang\",\n    \"lat\": 34.2999,\n    \"lng\": 108.4816,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": null,\n    \"population\": 541554.0,\n    \"id\": 1156215566\n  },\n  {\n    \"city\": \"Pingliang\",\n    \"city_ascii\": \"Pingliang\",\n    \"lat\": 35.5412,\n    \"lng\": 106.6819,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": \"minor\",\n    \"population\": 2068033.0,\n    \"id\": 1156216904\n  },\n  {\n    \"city\": \"Xiantao\",\n    \"city_ascii\": \"Xiantao\",\n    \"lat\": 30.3833,\n    \"lng\": 113.4,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 1140100.0,\n    \"id\": 1156216927\n  },\n  {\n    \"city\": \"Yanjiang\",\n    \"city_ascii\": \"Yanjiang\",\n    \"lat\": 30.1256,\n    \"lng\": 104.6397,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 2593843.0,\n    \"id\": 1156217114\n  },\n  {\n    \"city\": \"Shijiazhuang\",\n    \"city_ascii\": \"Shijiazhuang\",\n    \"lat\": 38.0422,\n    \"lng\": 114.5086,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": \"admin\",\n    \"population\": 4098243.0,\n    \"id\": 1156217541\n  },\n  {\n    \"city\": \"Yiyang\",\n    \"city_ascii\": \"Yiyang\",\n    \"lat\": 28.5833,\n    \"lng\": 112.3333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 4413800.0,\n    \"id\": 1156218615\n  },\n  {\n    \"city\": \"Yuyao\",\n    \"city_ascii\": \"Yuyao\",\n    \"lat\": 30.0372,\n    \"lng\": 121.1546,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 1095000.0,\n    \"id\": 1156221984\n  },\n  {\n    \"city\": \"Heze\",\n    \"city_ascii\": \"Heze\",\n    \"lat\": 35.2333,\n    \"lng\": 115.4333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 8795939.0,\n    \"id\": 1156225008\n  },\n  {\n    \"city\": \"Hejin\",\n    \"city_ascii\": \"Hejin\",\n    \"lat\": 35.5914,\n    \"lng\": 110.706,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": null,\n    \"population\": 395527.0,\n    \"id\": 1156225234\n  },\n  {\n    \"city\": \"Chuxiong\",\n    \"city_ascii\": \"Chuxiong\",\n    \"lat\": 25.0461,\n    \"lng\": 101.5436,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": null,\n    \"population\": 588620.0,\n    \"id\": 1156225985\n  },\n  {\n    \"city\": \"Shuozhou\",\n    \"city_ascii\": \"Shuozhou\",\n    \"lat\": 39.3408,\n    \"lng\": 112.4292,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": \"minor\",\n    \"population\": 1714857.0,\n    \"id\": 1156227167\n  },\n  {\n    \"city\": \"Beijing\",\n    \"city_ascii\": \"Beijing\",\n    \"lat\": 39.904,\n    \"lng\": 116.4075,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Beijing\",\n    \"capital\": \"primary\",\n    \"population\": 18522000.0,\n    \"id\": 1156228865\n  },\n  {\n    \"city\": \"Yichun\",\n    \"city_ascii\": \"Yichun\",\n    \"lat\": 27.8041,\n    \"lng\": 114.383,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": \"minor\",\n    \"population\": 5573200.0,\n    \"id\": 1156229590\n  },\n  {\n    \"city\": \"Yidu\",\n    \"city_ascii\": \"Yidu\",\n    \"lat\": 30.388,\n    \"lng\": 111.4505,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 384598.0,\n    \"id\": 1156230664\n  },\n  {\n    \"city\": \"Shihezi\",\n    \"city_ascii\": \"Shihezi\",\n    \"lat\": 44.3054,\n    \"lng\": 86.0804,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"minor\",\n    \"population\": 717000.0,\n    \"id\": 1156232270\n  },\n  {\n    \"city\": \"Huangshi\",\n    \"city_ascii\": \"Huangshi\",\n    \"lat\": 30.2018,\n    \"lng\": 115.0326,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"minor\",\n    \"population\": 2471700.0,\n    \"id\": 1156234290\n  },\n  {\n    \"city\": \"Guilin\",\n    \"city_ascii\": \"Guilin\",\n    \"lat\": 25.2819,\n    \"lng\": 110.2864,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 5085500.0,\n    \"id\": 1156235364\n  },\n  {\n    \"city\": \"Suihua\",\n    \"city_ascii\": \"Suihua\",\n    \"lat\": 46.6384,\n    \"lng\": 126.9808,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 5418153.0,\n    \"id\": 1156235493\n  },\n  {\n    \"city\": \"Jiangguanchi\",\n    \"city_ascii\": \"Jiangguanchi\",\n    \"lat\": 34.0244,\n    \"lng\": 113.8201,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 4379998.0,\n    \"id\": 1156235735\n  },\n  {\n    \"city\": \"Gaoyou\",\n    \"city_ascii\": \"Gaoyou\",\n    \"lat\": 32.7847,\n    \"lng\": 119.4432,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 811800.0,\n    \"id\": 1156235854\n  },\n  {\n    \"city\": \"Xin’an\",\n    \"city_ascii\": \"Xin'an\",\n    \"lat\": 34.3662,\n    \"lng\": 118.3369,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": null,\n    \"population\": 920628.0,\n    \"id\": 1156236053\n  },\n  {\n    \"city\": \"Suohe\",\n    \"city_ascii\": \"Suohe\",\n    \"lat\": 34.7879,\n    \"lng\": 113.392,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 626700.0,\n    \"id\": 1156236948\n  },\n  {\n    \"city\": \"Guangzhou\",\n    \"city_ascii\": \"Guangzhou\",\n    \"lat\": 23.13,\n    \"lng\": 113.26,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"admin\",\n    \"population\": 26940000.0,\n    \"id\": 1156237133\n  },\n  {\n    \"city\": \"Gaoping\",\n    \"city_ascii\": \"Gaoping\",\n    \"lat\": 35.7911,\n    \"lng\": 112.9259,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": null,\n    \"population\": 484862.0,\n    \"id\": 1156238773\n  },\n  {\n    \"city\": \"Anqing\",\n    \"city_ascii\": \"Anqing\",\n    \"lat\": 30.5,\n    \"lng\": 117.0333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 4723000.0,\n    \"id\": 1156238875\n  },\n  {\n    \"city\": \"Zhangjiakou Shi Xuanhua Qu\",\n    \"city_ascii\": \"Zhangjiakou Shi Xuanhua Qu\",\n    \"lat\": 40.5944,\n    \"lng\": 115.0243,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": \"minor\",\n    \"population\": 409745.0,\n    \"id\": 1156240430\n  },\n  {\n    \"city\": \"Harbin\",\n    \"city_ascii\": \"Harbin\",\n    \"lat\": 45.75,\n    \"lng\": 126.6333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"admin\",\n    \"population\": 3830000.0,\n    \"id\": 1156241528\n  },\n  {\n    \"city\": \"Zhangzhou\",\n    \"city_ascii\": \"Zhangzhou\",\n    \"lat\": 24.5093,\n    \"lng\": 117.6612,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 5140000.0,\n    \"id\": 1156241637\n  },\n  {\n    \"city\": \"Tongshan\",\n    \"city_ascii\": \"Tongshan\",\n    \"lat\": 34.261,\n    \"lng\": 117.1859,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 9083790.0,\n    \"id\": 1156241678\n  },\n  {\n    \"city\": \"Xi’an\",\n    \"city_ascii\": \"Xi'an\",\n    \"lat\": 34.2667,\n    \"lng\": 108.9,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": \"admin\",\n    \"population\": 12328000.0,\n    \"id\": 1156244079\n  },\n  {\n    \"city\": \"Fu’an\",\n    \"city_ascii\": \"Fu'an\",\n    \"lat\": 27.1,\n    \"lng\": 119.6333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 577000.0,\n    \"id\": 1156244234\n  },\n  {\n    \"city\": \"Yushan\",\n    \"city_ascii\": \"Yushan\",\n    \"lat\": 31.3867,\n    \"lng\": 120.9766,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 2092496.0,\n    \"id\": 1156245000\n  },\n  {\n    \"city\": \"Shuangyashan\",\n    \"city_ascii\": \"Shuangyashan\",\n    \"lat\": 46.6388,\n    \"lng\": 131.1545,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 1462626.0,\n    \"id\": 1156245904\n  },\n  {\n    \"city\": \"Fuyang\",\n    \"city_ascii\": \"Fuyang\",\n    \"lat\": 32.8986,\n    \"lng\": 115.8045,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": null,\n    \"population\": 8200264.0,\n    \"id\": 1156248008\n  },\n  {\n    \"city\": \"Guankou\",\n    \"city_ascii\": \"Guankou\",\n    \"lat\": 28.1417,\n    \"lng\": 113.625,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 1168056.0,\n    \"id\": 1156249346\n  },\n  {\n    \"city\": \"Mudanjiang\",\n    \"city_ascii\": \"Mudanjiang\",\n    \"lat\": 44.5861,\n    \"lng\": 129.5997,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 2798723.0,\n    \"id\": 1156249698\n  },\n  {\n    \"city\": \"Liaoyuan\",\n    \"city_ascii\": \"Liaoyuan\",\n    \"lat\": 42.8976,\n    \"lng\": 125.1381,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": null,\n    \"population\": 1176239.0,\n    \"id\": 1156249772\n  },\n  {\n    \"city\": \"Chengxiang\",\n    \"city_ascii\": \"Chengxiang\",\n    \"lat\": 31.4515,\n    \"lng\": 121.1043,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 831113.0,\n    \"id\": 1156254788\n  },\n  {\n    \"city\": \"Xingyi\",\n    \"city_ascii\": \"Xingyi\",\n    \"lat\": 25.091,\n    \"lng\": 104.9011,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": null,\n    \"population\": 1004132.0,\n    \"id\": 1156255316\n  },\n  {\n    \"city\": \"Ankang\",\n    \"city_ascii\": \"Ankang\",\n    \"lat\": 32.6877,\n    \"lng\": 109.0235,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": null,\n    \"population\": 2629906.0,\n    \"id\": 1156255711\n  },\n  {\n    \"city\": \"Daye\",\n    \"city_ascii\": \"Daye\",\n    \"lat\": 30.1003,\n    \"lng\": 114.9699,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 909724.0,\n    \"id\": 1156255811\n  },\n  {\n    \"city\": \"Baoding\",\n    \"city_ascii\": \"Baoding\",\n    \"lat\": 38.8671,\n    \"lng\": 115.4845,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 11860000.0,\n    \"id\": 1156256829\n  },\n  {\n    \"city\": \"Yingkou\",\n    \"city_ascii\": \"Yingkou\",\n    \"lat\": 40.6653,\n    \"lng\": 122.2297,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": \"minor\",\n    \"population\": 2428534.0,\n    \"id\": 1156257074\n  },\n  {\n    \"city\": \"Xinxing\",\n    \"city_ascii\": \"Xinxing\",\n    \"lat\": 39.8734,\n    \"lng\": 124.1453,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": \"minor\",\n    \"population\": 627475.0,\n    \"id\": 1156258586\n  },\n  {\n    \"city\": \"Guixi\",\n    \"city_ascii\": \"Guixi\",\n    \"lat\": 28.2861,\n    \"lng\": 117.2083,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": \"minor\",\n    \"population\": 647240.0,\n    \"id\": 1156259342\n  },\n  {\n    \"city\": \"Dongyang\",\n    \"city_ascii\": \"Dongyang\",\n    \"lat\": 29.2785,\n    \"lng\": 120.2282,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 804398.0,\n    \"id\": 1156259752\n  },\n  {\n    \"city\": \"Jieyang\",\n    \"city_ascii\": \"Jieyang\",\n    \"lat\": 23.5533,\n    \"lng\": 116.3649,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 6089400.0,\n    \"id\": 1156260378\n  },\n  {\n    \"city\": \"Nagqu\",\n    \"city_ascii\": \"Nagqu\",\n    \"lat\": 31.4766,\n    \"lng\": 92.0569,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Tibet\",\n    \"capital\": \"minor\",\n    \"population\": 504838.0,\n    \"id\": 1156260844\n  },\n  {\n    \"city\": \"Xindi\",\n    \"city_ascii\": \"Xindi\",\n    \"lat\": 29.8182,\n    \"lng\": 113.4653,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 819446.0,\n    \"id\": 1156263165\n  },\n  {\n    \"city\": \"Zhuangyuan\",\n    \"city_ascii\": \"Zhuangyuan\",\n    \"lat\": 37.3056,\n    \"lng\": 120.8275,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 626683.0,\n    \"id\": 1156263400\n  },\n  {\n    \"city\": \"Wusong\",\n    \"city_ascii\": \"Wusong\",\n    \"lat\": 30.9333,\n    \"lng\": 117.7667,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 1311726.0,\n    \"id\": 1156264408\n  },\n  {\n    \"city\": \"Hancheng\",\n    \"city_ascii\": \"Hancheng\",\n    \"lat\": 35.4768,\n    \"lng\": 110.4419,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": null,\n    \"population\": 391164.0,\n    \"id\": 1156265838\n  },\n  {\n    \"city\": \"Mishan\",\n    \"city_ascii\": \"Mishan\",\n    \"lat\": 45.542,\n    \"lng\": 131.8666,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 420000.0,\n    \"id\": 1156267144\n  },\n  {\n    \"city\": \"Hailin\",\n    \"city_ascii\": \"Hailin\",\n    \"lat\": 44.5735,\n    \"lng\": 129.3825,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 420000.0,\n    \"id\": 1156267191\n  },\n  {\n    \"city\": \"Guangshui\",\n    \"city_ascii\": \"Guangshui\",\n    \"lat\": 31.6189,\n    \"lng\": 113.8229,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 755910.0,\n    \"id\": 1156267419\n  },\n  {\n    \"city\": \"Bazhou\",\n    \"city_ascii\": \"Bazhou\",\n    \"lat\": 31.8576,\n    \"lng\": 106.7559,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 3283148.0,\n    \"id\": 1156271365\n  },\n  {\n    \"city\": \"Zhoukou\",\n    \"city_ascii\": \"Zhoukou\",\n    \"lat\": 33.625,\n    \"lng\": 114.6418,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 9026015.0,\n    \"id\": 1156272098\n  },\n  {\n    \"city\": \"Qingyang\",\n    \"city_ascii\": \"Qingyang\",\n    \"lat\": 24.8141,\n    \"lng\": 118.5792,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 2111000.0,\n    \"id\": 1156273372\n  },\n  {\n    \"city\": \"Xinyang\",\n    \"city_ascii\": \"Xinyang\",\n    \"lat\": 32.1264,\n    \"lng\": 114.0672,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 6234401.0,\n    \"id\": 1156273453\n  },\n  {\n    \"city\": \"Hangzhou\",\n    \"city_ascii\": \"Hangzhou\",\n    \"lat\": 30.25,\n    \"lng\": 120.1675,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"admin\",\n    \"population\": 9523000.0,\n    \"id\": 1156275243\n  },\n  {\n    \"city\": \"Jiexiu\",\n    \"city_ascii\": \"Jiexiu\",\n    \"lat\": 37.0282,\n    \"lng\": 111.9103,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": null,\n    \"population\": 406517.0,\n    \"id\": 1156275703\n  },\n  {\n    \"city\": \"Chifeng\",\n    \"city_ascii\": \"Chifeng\",\n    \"lat\": 42.2663,\n    \"lng\": 118.9223,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Inner Mongolia\",\n    \"capital\": \"minor\",\n    \"population\": 4341245.0,\n    \"id\": 1156277458\n  },\n  {\n    \"city\": \"Qamdo\",\n    \"city_ascii\": \"Qamdo\",\n    \"lat\": 31.1375,\n    \"lng\": 97.1777,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Tibet\",\n    \"capital\": \"minor\",\n    \"population\": 760966.0,\n    \"id\": 1156277802\n  },\n  {\n    \"city\": \"Ji’an\",\n    \"city_ascii\": \"Ji'an\",\n    \"lat\": 27.1172,\n    \"lng\": 114.9793,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": \"minor\",\n    \"population\": 4956600.0,\n    \"id\": 1156278215\n  },\n  {\n    \"city\": \"Jian’ou\",\n    \"city_ascii\": \"Jian'ou\",\n    \"lat\": 27.0387,\n    \"lng\": 118.3215,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 456000.0,\n    \"id\": 1156278784\n  },\n  {\n    \"city\": \"Shache\",\n    \"city_ascii\": \"Shache\",\n    \"lat\": 38.4261,\n    \"lng\": 77.25,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": null,\n    \"population\": 851374.0,\n    \"id\": 1156278934\n  },\n  {\n    \"city\": \"Ailan Mubage\",\n    \"city_ascii\": \"Ailan Mubage\",\n    \"lat\": 43.908,\n    \"lng\": 81.2777,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"minor\",\n    \"population\": 526745.0,\n    \"id\": 1156279608\n  },\n  {\n    \"city\": \"Lanzhou\",\n    \"city_ascii\": \"Lanzhou\",\n    \"lat\": 36.0617,\n    \"lng\": 103.8318,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": \"admin\",\n    \"population\": 3067141.0,\n    \"id\": 1156280566\n  },\n  {\n    \"city\": \"Yulinshi\",\n    \"city_ascii\": \"Yulinshi\",\n    \"lat\": 38.2655,\n    \"lng\": 109.7388,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": null,\n    \"population\": 3634750.0,\n    \"id\": 1156280672\n  },\n  {\n    \"city\": \"Taihe\",\n    \"city_ascii\": \"Taihe\",\n    \"lat\": 30.8706,\n    \"lng\": 105.3784,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 924531.0,\n    \"id\": 1156281983\n  },\n  {\n    \"city\": \"Huazhou\",\n    \"city_ascii\": \"Huazhou\",\n    \"lat\": 21.654,\n    \"lng\": 110.6294,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": null,\n    \"population\": 1302100.0,\n    \"id\": 1156282637\n  },\n  {\n    \"city\": \"Xiulin\",\n    \"city_ascii\": \"Xiulin\",\n    \"lat\": 29.7211,\n    \"lng\": 112.4037,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 577022.0,\n    \"id\": 1156284109\n  },\n  {\n    \"city\": \"Chenzhou\",\n    \"city_ascii\": \"Chenzhou\",\n    \"lat\": 25.7989,\n    \"lng\": 113.0267,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 4744500.0,\n    \"id\": 1156291915\n  },\n  {\n    \"city\": \"Yicheng\",\n    \"city_ascii\": \"Yicheng\",\n    \"lat\": 31.3697,\n    \"lng\": 119.8239,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 1285785.0,\n    \"id\": 1156292419\n  },\n  {\n    \"city\": \"Yuanping\",\n    \"city_ascii\": \"Yuanping\",\n    \"lat\": 38.7299,\n    \"lng\": 112.7134,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": null,\n    \"population\": 491213.0,\n    \"id\": 1156294277\n  },\n  {\n    \"city\": \"Sanming\",\n    \"city_ascii\": \"Sanming\",\n    \"lat\": 26.2658,\n    \"lng\": 117.6302,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 2580000.0,\n    \"id\": 1156294429\n  },\n  {\n    \"city\": \"Xingtai\",\n    \"city_ascii\": \"Xingtai\",\n    \"lat\": 37.0659,\n    \"lng\": 114.4753,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 7111106.0,\n    \"id\": 1156294952\n  },\n  {\n    \"city\": \"Minzhu\",\n    \"city_ascii\": \"Minzhu\",\n    \"lat\": 43.7192,\n    \"lng\": 127.337,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 453265.0,\n    \"id\": 1156295044\n  },\n  {\n    \"city\": \"Yingtan\",\n    \"city_ascii\": \"Yingtan\",\n    \"lat\": 28.2333,\n    \"lng\": 117.0,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": null,\n    \"population\": 1175000.0,\n    \"id\": 1156301061\n  },\n  {\n    \"city\": \"Lichuan\",\n    \"city_ascii\": \"Lichuan\",\n    \"lat\": 30.2965,\n    \"lng\": 108.9378,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 913700.0,\n    \"id\": 1156302762\n  },\n  {\n    \"city\": \"Feicheng\",\n    \"city_ascii\": \"Feicheng\",\n    \"lat\": 36.186,\n    \"lng\": 116.772,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 946627.0,\n    \"id\": 1156303834\n  },\n  {\n    \"city\": \"Jieshou\",\n    \"city_ascii\": \"Jieshou\",\n    \"lat\": 33.2605,\n    \"lng\": 115.3618,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": null,\n    \"population\": 650870.0,\n    \"id\": 1156304827\n  },\n  {\n    \"city\": \"Shenyang\",\n    \"city_ascii\": \"Shenyang\",\n    \"lat\": 41.8025,\n    \"lng\": 123.4281,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": \"admin\",\n    \"population\": 7964000.0,\n    \"id\": 1156309382\n  },\n  {\n    \"city\": \"Shaoyang\",\n    \"city_ascii\": \"Shaoyang\",\n    \"lat\": 27.2418,\n    \"lng\": 111.4725,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 7370500.0,\n    \"id\": 1156310366\n  },\n  {\n    \"city\": \"Qian’an\",\n    \"city_ascii\": \"Qian'an\",\n    \"lat\": 40.0059,\n    \"lng\": 118.6973,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 728160.0,\n    \"id\": 1156315498\n  },\n  {\n    \"city\": \"Wuhu\",\n    \"city_ascii\": \"Wuhu\",\n    \"lat\": 31.334,\n    \"lng\": 118.3622,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 3842100.0,\n    \"id\": 1156315512\n  },\n  {\n    \"city\": \"Taizhou\",\n    \"city_ascii\": \"Taizhou\",\n    \"lat\": 28.6583,\n    \"lng\": 121.4221,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 2162461.0,\n    \"id\": 1156322307\n  },\n  {\n    \"city\": \"Rucheng\",\n    \"city_ascii\": \"Rucheng\",\n    \"lat\": 32.3852,\n    \"lng\": 120.5634,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 1267066.0,\n    \"id\": 1156323529\n  },\n  {\n    \"city\": \"Yushu\",\n    \"city_ascii\": \"Yushu\",\n    \"lat\": 44.8249,\n    \"lng\": 126.5451,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 1304436.0,\n    \"id\": 1156326773\n  },\n  {\n    \"city\": \"Xiangshui\",\n    \"city_ascii\": \"Xiangshui\",\n    \"lat\": 26.5964,\n    \"lng\": 104.8314,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": null,\n    \"population\": 1221000.0,\n    \"id\": 1156328867\n  },\n  {\n    \"city\": \"Luohe\",\n    \"city_ascii\": \"Luohe\",\n    \"lat\": 33.583,\n    \"lng\": 114.0109,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 2544266.0,\n    \"id\": 1156330876\n  },\n  {\n    \"city\": \"Taixing\",\n    \"city_ascii\": \"Taixing\",\n    \"lat\": 32.1724,\n    \"lng\": 120.0142,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 1073921.0,\n    \"id\": 1156331200\n  },\n  {\n    \"city\": \"Hai’an\",\n    \"city_ascii\": \"Hai'an\",\n    \"lat\": 32.532,\n    \"lng\": 120.4604,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 874334.0,\n    \"id\": 1156332302\n  },\n  {\n    \"city\": \"Hefei\",\n    \"city_ascii\": \"Hefei\",\n    \"lat\": 31.8639,\n    \"lng\": 117.2808,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"admin\",\n    \"population\": 4216940.0,\n    \"id\": 1156332710\n  },\n  {\n    \"city\": \"Lianran\",\n    \"city_ascii\": \"Lianran\",\n    \"lat\": 24.9211,\n    \"lng\": 102.4778,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": \"minor\",\n    \"population\": 341341.0,\n    \"id\": 1156332794\n  },\n  {\n    \"city\": \"Huzhou\",\n    \"city_ascii\": \"Huzhou\",\n    \"lat\": 30.8925,\n    \"lng\": 120.0875,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 1558826.0,\n    \"id\": 1156335543\n  },\n  {\n    \"city\": \"Heihe\",\n    \"city_ascii\": \"Heihe\",\n    \"lat\": 50.2458,\n    \"lng\": 127.4886,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 1673899.0,\n    \"id\": 1156339225\n  },\n  {\n    \"city\": \"Fuyang\",\n    \"city_ascii\": \"Fuyang\",\n    \"lat\": 30.0553,\n    \"lng\": 119.95,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 771000.0,\n    \"id\": 1156340393\n  },\n  {\n    \"city\": \"Jiangshan\",\n    \"city_ascii\": \"Jiangshan\",\n    \"lat\": 28.7412,\n    \"lng\": 118.6225,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 467862.0,\n    \"id\": 1156346497\n  },\n  {\n    \"city\": \"Danjiangkou\",\n    \"city_ascii\": \"Danjiangkou\",\n    \"lat\": 32.5408,\n    \"lng\": 111.5098,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 443755.0,\n    \"id\": 1156347994\n  },\n  {\n    \"city\": \"Jiamusi\",\n    \"city_ascii\": \"Jiamusi\",\n    \"lat\": 46.8081,\n    \"lng\": 130.3653,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 2552097.0,\n    \"id\": 1156350864\n  },\n  {\n    \"city\": \"Jiangjiafan\",\n    \"city_ascii\": \"Jiangjiafan\",\n    \"lat\": 31.0238,\n    \"lng\": 111.9709,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 400000.0,\n    \"id\": 1156352568\n  },\n  {\n    \"city\": \"Huaihua\",\n    \"city_ascii\": \"Huaihua\",\n    \"lat\": 27.5494,\n    \"lng\": 109.9592,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 4979600.0,\n    \"id\": 1156353465\n  },\n  {\n    \"city\": \"Bozhou\",\n    \"city_ascii\": \"Bozhou\",\n    \"lat\": 33.8626,\n    \"lng\": 115.7742,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": null,\n    \"population\": 4996844.0,\n    \"id\": 1156356860\n  },\n  {\n    \"city\": \"Tongliao\",\n    \"city_ascii\": \"Tongliao\",\n    \"lat\": 43.6172,\n    \"lng\": 122.264,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Inner Mongolia\",\n    \"capital\": \"minor\",\n    \"population\": 3139153.0,\n    \"id\": 1156358686\n  },\n  {\n    \"city\": \"Yinchuan\",\n    \"city_ascii\": \"Yinchuan\",\n    \"lat\": 38.4795,\n    \"lng\": 106.2254,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Ningxia\",\n    \"capital\": \"admin\",\n    \"population\": 1901793.0,\n    \"id\": 1156359072\n  },\n  {\n    \"city\": \"Liuzhou\",\n    \"city_ascii\": \"Liuzhou\",\n    \"lat\": 24.3264,\n    \"lng\": 109.4281,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 4157934.0,\n    \"id\": 1156360785\n  },\n  {\n    \"city\": \"Meizhou\",\n    \"city_ascii\": \"Meizhou\",\n    \"lat\": 24.2998,\n    \"lng\": 116.1191,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 4378800.0,\n    \"id\": 1156361028\n  },\n  {\n    \"city\": \"Liangshi\",\n    \"city_ascii\": \"Liangshi\",\n    \"lat\": 27.2578,\n    \"lng\": 111.7351,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 1335900.0,\n    \"id\": 1156366507\n  },\n  {\n    \"city\": \"Xinmin\",\n    \"city_ascii\": \"Xinmin\",\n    \"lat\": 41.9952,\n    \"lng\": 122.8224,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 680000.0,\n    \"id\": 1156368551\n  },\n  {\n    \"city\": \"Lhasa\",\n    \"city_ascii\": \"Lhasa\",\n    \"lat\": 29.6534,\n    \"lng\": 91.1719,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Tibet\",\n    \"capital\": \"admin\",\n    \"population\": 902500.0,\n    \"id\": 1156369972\n  },\n  {\n    \"city\": \"Sanya\",\n    \"city_ascii\": \"Sanya\",\n    \"lat\": 18.2533,\n    \"lng\": 109.5036,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hainan\",\n    \"capital\": \"minor\",\n    \"population\": 1031396.0,\n    \"id\": 1156373900\n  },\n  {\n    \"city\": \"Guang’an\",\n    \"city_ascii\": \"Guang'an\",\n    \"lat\": 30.4673,\n    \"lng\": 106.6336,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 3205476.0,\n    \"id\": 1156377302\n  },\n  {\n    \"city\": \"Beipiao\",\n    \"city_ascii\": \"Beipiao\",\n    \"lat\": 41.802,\n    \"lng\": 120.7621,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 496164.0,\n    \"id\": 1156378599\n  },\n  {\n    \"city\": \"Zibo\",\n    \"city_ascii\": \"Zibo\",\n    \"lat\": 36.7831,\n    \"lng\": 118.0497,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 2631647.0,\n    \"id\": 1156381094\n  },\n  {\n    \"city\": \"Hanzhong\",\n    \"city_ascii\": \"Hanzhong\",\n    \"lat\": 33.0794,\n    \"lng\": 107.026,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": null,\n    \"population\": 3416196.0,\n    \"id\": 1156382678\n  },\n  {\n    \"city\": \"Guli\",\n    \"city_ascii\": \"Guli\",\n    \"lat\": 28.9008,\n    \"lng\": 120.0284,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 723490.0,\n    \"id\": 1156383681\n  },\n  {\n    \"city\": \"Shiyan\",\n    \"city_ascii\": \"Shiyan\",\n    \"lat\": 32.6351,\n    \"lng\": 110.7755,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"minor\",\n    \"population\": 3398000.0,\n    \"id\": 1156383921\n  },\n  {\n    \"city\": \"Fangting\",\n    \"city_ascii\": \"Fangting\",\n    \"lat\": 31.1282,\n    \"lng\": 104.1695,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 412758.0,\n    \"id\": 1156384608\n  },\n  {\n    \"city\": \"Wenlan\",\n    \"city_ascii\": \"Wenlan\",\n    \"lat\": 23.3989,\n    \"lng\": 103.3631,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": \"minor\",\n    \"population\": 585976.0,\n    \"id\": 1156385754\n  },\n  {\n    \"city\": \"Yingmen\",\n    \"city_ascii\": \"Yingmen\",\n    \"lat\": 39.9487,\n    \"lng\": 97.4395,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": null,\n    \"population\": 350000.0,\n    \"id\": 1156386711\n  },\n  {\n    \"city\": \"Jixi\",\n    \"city_ascii\": \"Jixi\",\n    \"lat\": 45.2937,\n    \"lng\": 130.965,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 1862165.0,\n    \"id\": 1156393765\n  },\n  {\n    \"city\": \"Daqing\",\n    \"city_ascii\": \"Daqing\",\n    \"lat\": 46.5979,\n    \"lng\": 125.008,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 2904532.0,\n    \"id\": 1156403962\n  },\n  {\n    \"city\": \"Fujin\",\n    \"city_ascii\": \"Fujin\",\n    \"lat\": 47.2489,\n    \"lng\": 132.0341,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 470000.0,\n    \"id\": 1156404715\n  },\n  {\n    \"city\": \"Yanji\",\n    \"city_ascii\": \"Yanji\",\n    \"lat\": 42.9044,\n    \"lng\": 129.5067,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 513072.0,\n    \"id\": 1156405468\n  },\n  {\n    \"city\": \"Shangrao\",\n    \"city_ascii\": \"Shangrao\",\n    \"lat\": 28.4419,\n    \"lng\": 117.9633,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": \"minor\",\n    \"population\": 6810700.0,\n    \"id\": 1156405492\n  },\n  {\n    \"city\": \"Hejian\",\n    \"city_ascii\": \"Hejian\",\n    \"lat\": 38.4451,\n    \"lng\": 116.0897,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 810306.0,\n    \"id\": 1156405731\n  },\n  {\n    \"city\": \"Anlu\",\n    \"city_ascii\": \"Anlu\",\n    \"lat\": 31.2575,\n    \"lng\": 113.6783,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"minor\",\n    \"population\": 720000.0,\n    \"id\": 1156406202\n  },\n  {\n    \"city\": \"Zhuanghe\",\n    \"city_ascii\": \"Zhuanghe\",\n    \"lat\": 39.6896,\n    \"lng\": 122.9664,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 905852.0,\n    \"id\": 1156410076\n  },\n  {\n    \"city\": \"Ezhou\",\n    \"city_ascii\": \"Ezhou\",\n    \"lat\": 30.3972,\n    \"lng\": 114.8842,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"minor\",\n    \"population\": 1079353.0,\n    \"id\": 1156414637\n  },\n  {\n    \"city\": \"Anshun\",\n    \"city_ascii\": \"Anshun\",\n    \"lat\": 26.2456,\n    \"lng\": 105.934,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": null,\n    \"population\": 2353100.0,\n    \"id\": 1156415948\n  },\n  {\n    \"city\": \"Linfen\",\n    \"city_ascii\": \"Linfen\",\n    \"lat\": 36.0812,\n    \"lng\": 111.5087,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": null,\n    \"population\": 4316610.0,\n    \"id\": 1156416074\n  },\n  {\n    \"city\": \"Mianyang\",\n    \"city_ascii\": \"Mianyang\",\n    \"lat\": 31.4669,\n    \"lng\": 104.7385,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 4868243.0,\n    \"id\": 1156417758\n  },\n  {\n    \"city\": \"Beihai\",\n    \"city_ascii\": \"Beihai\",\n    \"lat\": 21.4667,\n    \"lng\": 109.1,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 1853227.0,\n    \"id\": 1156421449\n  },\n  {\n    \"city\": \"Chengdu\",\n    \"city_ascii\": \"Chengdu\",\n    \"lat\": 30.66,\n    \"lng\": 104.0633,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"admin\",\n    \"population\": 14645000.0,\n    \"id\": 1156421555\n  },\n  {\n    \"city\": \"Xinshi\",\n    \"city_ascii\": \"Xinshi\",\n    \"lat\": 31.0236,\n    \"lng\": 113.1079,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"minor\",\n    \"population\": 636776.0,\n    \"id\": 1156422214\n  },\n  {\n    \"city\": \"Xuanzhou\",\n    \"city_ascii\": \"Xuanzhou\",\n    \"lat\": 30.9475,\n    \"lng\": 118.7518,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": null,\n    \"population\": 2532938.0,\n    \"id\": 1156424311\n  },\n  {\n    \"city\": \"Beining\",\n    \"city_ascii\": \"Beining\",\n    \"lat\": 41.5961,\n    \"lng\": 121.7928,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 514898.0,\n    \"id\": 1156424678\n  },\n  {\n    \"city\": \"Nangong\",\n    \"city_ascii\": \"Nangong\",\n    \"lat\": 37.3606,\n    \"lng\": 115.3803,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 476096.0,\n    \"id\": 1156426803\n  },\n  {\n    \"city\": \"Puyang\",\n    \"city_ascii\": \"Puyang\",\n    \"lat\": 35.7639,\n    \"lng\": 115.03,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 3598740.0,\n    \"id\": 1156431924\n  },\n  {\n    \"city\": \"Baicheng\",\n    \"city_ascii\": \"Baicheng\",\n    \"lat\": 45.6148,\n    \"lng\": 122.832,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 2032356.0,\n    \"id\": 1156435764\n  },\n  {\n    \"city\": \"Aksu\",\n    \"city_ascii\": \"Aksu\",\n    \"lat\": 41.185,\n    \"lng\": 80.2904,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"minor\",\n    \"population\": 535657.0,\n    \"id\": 1156436913\n  },\n  {\n    \"city\": \"Taozhou\",\n    \"city_ascii\": \"Taozhou\",\n    \"lat\": 30.8956,\n    \"lng\": 119.411,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 499132.0,\n    \"id\": 1156438524\n  },\n  {\n    \"city\": \"Chongzuo\",\n    \"city_ascii\": \"Chongzuo\",\n    \"lat\": 22.4167,\n    \"lng\": 107.3667,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 2099400.0,\n    \"id\": 1156438670\n  },\n  {\n    \"city\": \"Bengbu\",\n    \"city_ascii\": \"Bengbu\",\n    \"lat\": 32.9354,\n    \"lng\": 117.3531,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": null,\n    \"population\": 3296408.0,\n    \"id\": 1156440668\n  },\n  {\n    \"city\": \"Kaiyuan\",\n    \"city_ascii\": \"Kaiyuan\",\n    \"lat\": 36.0656,\n    \"lng\": 113.8153,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 1160000.0,\n    \"id\": 1156441554\n  },\n  {\n    \"city\": \"Jianshe\",\n    \"city_ascii\": \"Jianshe\",\n    \"lat\": 34.2189,\n    \"lng\": 113.7693,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 687130.0,\n    \"id\": 1156444449\n  },\n  {\n    \"city\": \"Changde\",\n    \"city_ascii\": \"Changde\",\n    \"lat\": 29.0397,\n    \"lng\": 111.6839,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 5827200.0,\n    \"id\": 1156449091\n  },\n  {\n    \"city\": \"Sizhan\",\n    \"city_ascii\": \"Sizhan\",\n    \"lat\": 39.0099,\n    \"lng\": 106.3694,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Ningxia\",\n    \"capital\": null,\n    \"population\": 751389.0,\n    \"id\": 1156450911\n  },\n  {\n    \"city\": \"Linhai\",\n    \"city_ascii\": \"Linhai\",\n    \"lat\": 28.8523,\n    \"lng\": 121.1409,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 1028813.0,\n    \"id\": 1156451663\n  },\n  {\n    \"city\": \"Fenyang\",\n    \"city_ascii\": \"Fenyang\",\n    \"lat\": 37.2647,\n    \"lng\": 111.7775,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": null,\n    \"population\": 416212.0,\n    \"id\": 1156455704\n  },\n  {\n    \"city\": \"Xinji\",\n    \"city_ascii\": \"Xinji\",\n    \"lat\": 37.9423,\n    \"lng\": 115.2118,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 615919.0,\n    \"id\": 1156456552\n  },\n  {\n    \"city\": \"Shantou\",\n    \"city_ascii\": \"Shantou\",\n    \"lat\": 23.3735,\n    \"lng\": 116.6941,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 4312192.0,\n    \"id\": 1156457499\n  },\n  {\n    \"city\": \"Hezhou\",\n    \"city_ascii\": \"Hezhou\",\n    \"lat\": 24.4164,\n    \"lng\": 111.5478,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 2072600.0,\n    \"id\": 1156459799\n  },\n  {\n    \"city\": \"Shuizhai\",\n    \"city_ascii\": \"Shuizhai\",\n    \"lat\": 33.4433,\n    \"lng\": 114.8994,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 1003698.0,\n    \"id\": 1156462734\n  },\n  {\n    \"city\": \"Yanjiao\",\n    \"city_ascii\": \"Yanjiao\",\n    \"lat\": 39.9432,\n    \"lng\": 116.8036,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 363809.0,\n    \"id\": 1156470847\n  },\n  {\n    \"city\": \"Weihai\",\n    \"city_ascii\": \"Weihai\",\n    \"lat\": 37.5,\n    \"lng\": 122.1,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 2906548.0,\n    \"id\": 1156473300\n  },\n  {\n    \"city\": \"Meihekou\",\n    \"city_ascii\": \"Meihekou\",\n    \"lat\": 42.5279,\n    \"lng\": 125.678,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 618251.0,\n    \"id\": 1156474288\n  },\n  {\n    \"city\": \"Sanhe\",\n    \"city_ascii\": \"Sanhe\",\n    \"lat\": 39.9808,\n    \"lng\": 117.0701,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 652042.0,\n    \"id\": 1156476348\n  },\n  {\n    \"city\": \"Wafangdian\",\n    \"city_ascii\": \"Wafangdian\",\n    \"lat\": 39.6271,\n    \"lng\": 121.9972,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 1024876.0,\n    \"id\": 1156476417\n  },\n  {\n    \"city\": \"Kunming\",\n    \"city_ascii\": \"Kunming\",\n    \"lat\": 25.0433,\n    \"lng\": 102.7061,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": \"admin\",\n    \"population\": 4422686.0,\n    \"id\": 1156477539\n  },\n  {\n    \"city\": \"Dongguan\",\n    \"city_ascii\": \"Dongguan\",\n    \"lat\": 23.0475,\n    \"lng\": 113.7493,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 10646000.0,\n    \"id\": 1156478242\n  },\n  {\n    \"city\": \"Huilong\",\n    \"city_ascii\": \"Huilong\",\n    \"lat\": 31.8131,\n    \"lng\": 121.6574,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 972525.0,\n    \"id\": 1156485081\n  },\n  {\n    \"city\": \"Gaobeidian\",\n    \"city_ascii\": \"Gaobeidian\",\n    \"lat\": 39.3257,\n    \"lng\": 115.8678,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 640280.0,\n    \"id\": 1156487293\n  },\n  {\n    \"city\": \"Qufu\",\n    \"city_ascii\": \"Qufu\",\n    \"lat\": 35.6,\n    \"lng\": 116.9833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 640498.0,\n    \"id\": 1156490037\n  },\n  {\n    \"city\": \"Lianyuan\",\n    \"city_ascii\": \"Lianyuan\",\n    \"lat\": 27.6961,\n    \"lng\": 111.6659,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 1162928.0,\n    \"id\": 1156490109\n  },\n  {\n    \"city\": \"Jiaxing\",\n    \"city_ascii\": \"Jiaxing\",\n    \"lat\": 30.7522,\n    \"lng\": 120.75,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 1518654.0,\n    \"id\": 1156491661\n  },\n  {\n    \"city\": \"Lu’an\",\n    \"city_ascii\": \"Lu'an\",\n    \"lat\": 31.7542,\n    \"lng\": 116.5078,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 5611701.0,\n    \"id\": 1156499624\n  },\n  {\n    \"city\": \"Zhanjiang\",\n    \"city_ascii\": \"Zhanjiang\",\n    \"lat\": 21.1967,\n    \"lng\": 110.4031,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 7332000.0,\n    \"id\": 1156502170\n  },\n  {\n    \"city\": \"Guankou\",\n    \"city_ascii\": \"Guankou\",\n    \"lat\": 30.9933,\n    \"lng\": 103.624,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": null,\n    \"population\": 671200.0,\n    \"id\": 1156503907\n  },\n  {\n    \"city\": \"Zhuji\",\n    \"city_ascii\": \"Zhuji\",\n    \"lat\": 29.7169,\n    \"lng\": 120.2314,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 1157938.0,\n    \"id\": 1156504227\n  },\n  {\n    \"city\": \"Jining\",\n    \"city_ascii\": \"Jining\",\n    \"lat\": 35.4,\n    \"lng\": 116.5667,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 8357897.0,\n    \"id\": 1156504601\n  },\n  {\n    \"city\": \"Zhongba\",\n    \"city_ascii\": \"Zhongba\",\n    \"lat\": 31.7761,\n    \"lng\": 104.7406,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 762140.0,\n    \"id\": 1156515985\n  },\n  {\n    \"city\": \"Neijiang\",\n    \"city_ascii\": \"Neijiang\",\n    \"lat\": 29.5872,\n    \"lng\": 105.0635,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 3702847.0,\n    \"id\": 1156516335\n  },\n  {\n    \"city\": \"Dingxi\",\n    \"city_ascii\": \"Dingxi\",\n    \"lat\": 35.5806,\n    \"lng\": 104.6263,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": \"minor\",\n    \"population\": 2698624.0,\n    \"id\": 1156518274\n  },\n  {\n    \"city\": \"Fengcheng\",\n    \"city_ascii\": \"Fengcheng\",\n    \"lat\": 40.4543,\n    \"lng\": 124.0646,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 543933.0,\n    \"id\": 1156519626\n  },\n  {\n    \"city\": \"Gaoping\",\n    \"city_ascii\": \"Gaoping\",\n    \"lat\": 30.7824,\n    \"lng\": 106.1281,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 2174000.0,\n    \"id\": 1156522457\n  },\n  {\n    \"city\": \"Zhufeng\",\n    \"city_ascii\": \"Zhufeng\",\n    \"lat\": 36.0,\n    \"lng\": 119.4167,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 1081960.0,\n    \"id\": 1156522825\n  },\n  {\n    \"city\": \"Dezhou\",\n    \"city_ascii\": \"Dezhou\",\n    \"lat\": 37.4513,\n    \"lng\": 116.3105,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 5611194.0,\n    \"id\": 1156524080\n  },\n  {\n    \"city\": \"Xiangxiang\",\n    \"city_ascii\": \"Xiangxiang\",\n    \"lat\": 27.7389,\n    \"lng\": 112.5223,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 787216.0,\n    \"id\": 1156524101\n  },\n  {\n    \"city\": \"Huangshan\",\n    \"city_ascii\": \"Huangshan\",\n    \"lat\": 29.7132,\n    \"lng\": 118.3151,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 1358980.0,\n    \"id\": 1156527426\n  },\n  {\n    \"city\": \"Sanmenxia\",\n    \"city_ascii\": \"Sanmenxia\",\n    \"lat\": 34.7736,\n    \"lng\": 111.195,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 2234018.0,\n    \"id\": 1156529682\n  },\n  {\n    \"city\": \"Fuding\",\n    \"city_ascii\": \"Fuding\",\n    \"lat\": 27.2,\n    \"lng\": 120.2,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 542000.0,\n    \"id\": 1156530120\n  },\n  {\n    \"city\": \"Yucheng\",\n    \"city_ascii\": \"Yucheng\",\n    \"lat\": 36.9329,\n    \"lng\": 116.6403,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 522878.0,\n    \"id\": 1156530681\n  },\n  {\n    \"city\": \"Fangchenggang\",\n    \"city_ascii\": \"Fangchenggang\",\n    \"lat\": 21.6,\n    \"lng\": 108.3,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 1046068.0,\n    \"id\": 1156532454\n  },\n  {\n    \"city\": \"Xingren\",\n    \"city_ascii\": \"Xingren\",\n    \"lat\": 25.4352,\n    \"lng\": 105.1907,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": null,\n    \"population\": 417919.0,\n    \"id\": 1156533633\n  },\n  {\n    \"city\": \"Dongtai\",\n    \"city_ascii\": \"Dongtai\",\n    \"lat\": 32.8534,\n    \"lng\": 120.3037,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 990306.0,\n    \"id\": 1156536785\n  },\n  {\n    \"city\": \"Zunyi\",\n    \"city_ascii\": \"Zunyi\",\n    \"lat\": 27.705,\n    \"lng\": 106.9336,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": null,\n    \"population\": 6606675.0,\n    \"id\": 1156539782\n  },\n  {\n    \"city\": \"Hegang\",\n    \"city_ascii\": \"Hegang\",\n    \"lat\": 47.3139,\n    \"lng\": 130.2775,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 1058665.0,\n    \"id\": 1156541759\n  },\n  {\n    \"city\": \"Xinhualu\",\n    \"city_ascii\": \"Xinhualu\",\n    \"lat\": 34.3962,\n    \"lng\": 113.7249,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 758079.0,\n    \"id\": 1156544851\n  },\n  {\n    \"city\": \"Jianguang\",\n    \"city_ascii\": \"Jianguang\",\n    \"lat\": 28.1958,\n    \"lng\": 115.7833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": null,\n    \"population\": 1507402.0,\n    \"id\": 1156545200\n  },\n  {\n    \"city\": \"Yan’an\",\n    \"city_ascii\": \"Yan'an\",\n    \"lat\": 36.5952,\n    \"lng\": 109.4863,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": null,\n    \"population\": 2282581.0,\n    \"id\": 1156546342\n  },\n  {\n    \"city\": \"Baoshan\",\n    \"city_ascii\": \"Baoshan\",\n    \"lat\": 25.1211,\n    \"lng\": 99.169,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": null,\n    \"population\": 2627000.0,\n    \"id\": 1156546994\n  },\n  {\n    \"city\": \"Jinhua\",\n    \"city_ascii\": \"Jinhua\",\n    \"lat\": 29.1046,\n    \"lng\": 119.6494,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 1463990.0,\n    \"id\": 1156547188\n  },\n  {\n    \"city\": \"Chaozhou\",\n    \"city_ascii\": \"Chaozhou\",\n    \"lat\": 23.67,\n    \"lng\": 116.63,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 2656600.0,\n    \"id\": 1156549118\n  },\n  {\n    \"city\": \"Zêtang\",\n    \"city_ascii\": \"Zetang\",\n    \"lat\": 29.238,\n    \"lng\": 91.771,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Tibet\",\n    \"capital\": null,\n    \"population\": 382610.0,\n    \"id\": 1156561299\n  },\n  {\n    \"city\": \"Binzhou\",\n    \"city_ascii\": \"Binzhou\",\n    \"lat\": 37.3806,\n    \"lng\": 118.0125,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 3928568.0,\n    \"id\": 1156564962\n  },\n  {\n    \"city\": \"Maoming\",\n    \"city_ascii\": \"Maoming\",\n    \"lat\": 21.6618,\n    \"lng\": 110.9178,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 6313200.0,\n    \"id\": 1156568722\n  },\n  {\n    \"city\": \"Chengjiao\",\n    \"city_ascii\": \"Chengjiao\",\n    \"lat\": 35.4043,\n    \"lng\": 114.0593,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 495744.0,\n    \"id\": 1156571332\n  },\n  {\n    \"city\": \"Wanyuan\",\n    \"city_ascii\": \"Wanyuan\",\n    \"lat\": 32.0691,\n    \"lng\": 108.0351,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 407594.0,\n    \"id\": 1156571429\n  },\n  {\n    \"city\": \"Turpan\",\n    \"city_ascii\": \"Turpan\",\n    \"lat\": 42.9512,\n    \"lng\": 89.1895,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"minor\",\n    \"population\": 622903.0,\n    \"id\": 1156573684\n  },\n  {\n    \"city\": \"Shuanghe\",\n    \"city_ascii\": \"Shuanghe\",\n    \"lat\": 30.3866,\n    \"lng\": 106.7756,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 360000.0,\n    \"id\": 1156573894\n  },\n  {\n    \"city\": \"Wenchang\",\n    \"city_ascii\": \"Wenchang\",\n    \"lat\": 31.054,\n    \"lng\": 116.9507,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 664455.0,\n    \"id\": 1156574542\n  },\n  {\n    \"city\": \"Wuhai\",\n    \"city_ascii\": \"Wuhai\",\n    \"lat\": 39.6844,\n    \"lng\": 106.8158,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Inner Mongolia\",\n    \"capital\": \"minor\",\n    \"population\": 532902.0,\n    \"id\": 1156575615\n  },\n  {\n    \"city\": \"Da’an\",\n    \"city_ascii\": \"Da'an\",\n    \"lat\": 45.505,\n    \"lng\": 124.2863,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 418232.0,\n    \"id\": 1156577983\n  },\n  {\n    \"city\": \"Danyang\",\n    \"city_ascii\": \"Danyang\",\n    \"lat\": 31.9948,\n    \"lng\": 119.575,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": null,\n    \"population\": 980662.0,\n    \"id\": 1156578273\n  },\n  {\n    \"city\": \"Zhongshan\",\n    \"city_ascii\": \"Zhongshan\",\n    \"lat\": 22.5333,\n    \"lng\": 113.35,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 2909633.0,\n    \"id\": 1156579621\n  },\n  {\n    \"city\": \"Huludao\",\n    \"city_ascii\": \"Huludao\",\n    \"lat\": 40.7094,\n    \"lng\": 120.8378,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": \"minor\",\n    \"population\": 2623541.0,\n    \"id\": 1156580218\n  },\n  {\n    \"city\": \"Luzhou\",\n    \"city_ascii\": \"Luzhou\",\n    \"lat\": 28.8918,\n    \"lng\": 105.4409,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 4218427.0,\n    \"id\": 1156582079\n  },\n  {\n    \"city\": \"Dangyang\",\n    \"city_ascii\": \"Dangyang\",\n    \"lat\": 30.8258,\n    \"lng\": 111.791,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 560000.0,\n    \"id\": 1156585505\n  },\n  {\n    \"city\": \"Qingzhen\",\n    \"city_ascii\": \"Qingzhen\",\n    \"lat\": 26.5555,\n    \"lng\": 106.4646,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": null,\n    \"population\": 467992.0,\n    \"id\": 1156587033\n  },\n  {\n    \"city\": \"Yutan\",\n    \"city_ascii\": \"Yutan\",\n    \"lat\": 28.3147,\n    \"lng\": 112.554,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 1368117.0,\n    \"id\": 1156592042\n  },\n  {\n    \"city\": \"Anqiu\",\n    \"city_ascii\": \"Anqiu\",\n    \"lat\": 36.3619,\n    \"lng\": 119.1072,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 947723.0,\n    \"id\": 1156592047\n  },\n  {\n    \"city\": \"Zhaodong\",\n    \"city_ascii\": \"Zhaodong\",\n    \"lat\": 46.0635,\n    \"lng\": 125.9773,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 666532.0,\n    \"id\": 1156601489\n  },\n  {\n    \"city\": \"Nanning\",\n    \"city_ascii\": \"Nanning\",\n    \"lat\": 22.8192,\n    \"lng\": 108.315,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"admin\",\n    \"population\": 3837978.0,\n    \"id\": 1156605439\n  },\n  {\n    \"city\": \"Sihui\",\n    \"city_ascii\": \"Sihui\",\n    \"lat\": 23.3448,\n    \"lng\": 112.6956,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": null,\n    \"population\": 593400.0,\n    \"id\": 1156609451\n  },\n  {\n    \"city\": \"Nehe\",\n    \"city_ascii\": \"Nehe\",\n    \"lat\": 48.48,\n    \"lng\": 124.8738,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 740000.0,\n    \"id\": 1156609562\n  },\n  {\n    \"city\": \"Lecheng\",\n    \"city_ascii\": \"Lecheng\",\n    \"lat\": 25.1307,\n    \"lng\": 113.3472,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 419500.0,\n    \"id\": 1156612198\n  },\n  {\n    \"city\": \"Shaoguan\",\n    \"city_ascii\": \"Shaoguan\",\n    \"lat\": 24.8011,\n    \"lng\": 113.5927,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 2997600.0,\n    \"id\": 1156617066\n  },\n  {\n    \"city\": \"Xinzhou\",\n    \"city_ascii\": \"Xinzhou\",\n    \"lat\": 38.4178,\n    \"lng\": 112.7233,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": \"minor\",\n    \"population\": 3067501.0,\n    \"id\": 1156617534\n  },\n  {\n    \"city\": \"Wuzhou\",\n    \"city_ascii\": \"Wuzhou\",\n    \"lat\": 23.4833,\n    \"lng\": 111.3167,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 3061100.0,\n    \"id\": 1156620133\n  },\n  {\n    \"city\": \"Ning’an\",\n    \"city_ascii\": \"Ning'an\",\n    \"lat\": 44.3439,\n    \"lng\": 129.4656,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 440000.0,\n    \"id\": 1156629205\n  },\n  {\n    \"city\": \"Zhongxiang\",\n    \"city_ascii\": \"Zhongxiang\",\n    \"lat\": 31.169,\n    \"lng\": 112.5853,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 1022514.0,\n    \"id\": 1156631720\n  },\n  {\n    \"city\": \"Taiyuan\",\n    \"city_ascii\": \"Taiyuan\",\n    \"lat\": 37.8733,\n    \"lng\": 112.5425,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": \"admin\",\n    \"population\": 3875053.0,\n    \"id\": 1156632014\n  },\n  {\n    \"city\": \"Longba\",\n    \"city_ascii\": \"Longba\",\n    \"lat\": 33.535,\n    \"lng\": 105.349,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": null,\n    \"population\": 2567718.0,\n    \"id\": 1156633259\n  },\n  {\n    \"city\": \"Huai’an\",\n    \"city_ascii\": \"Huai'an\",\n    \"lat\": 33.5058,\n    \"lng\": 119.1392,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": null,\n    \"population\": 2632788.0,\n    \"id\": 1156634228\n  },\n  {\n    \"city\": \"Zhenzhou\",\n    \"city_ascii\": \"Zhenzhou\",\n    \"lat\": 32.2739,\n    \"lng\": 119.1619,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 564021.0,\n    \"id\": 1156634387\n  },\n  {\n    \"city\": \"Nanjing\",\n    \"city_ascii\": \"Nanjing\",\n    \"lat\": 32.0608,\n    \"lng\": 118.7789,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"admin\",\n    \"population\": 8422000.0,\n    \"id\": 1156644065\n  },\n  {\n    \"city\": \"Pudong\",\n    \"city_ascii\": \"Pudong\",\n    \"lat\": 31.2231,\n    \"lng\": 121.5397,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanghai\",\n    \"capital\": \"minor\",\n    \"population\": 5681512.0,\n    \"id\": 1156644508\n  },\n  {\n    \"city\": \"Jilin\",\n    \"city_ascii\": \"Jilin\",\n    \"lat\": 43.8519,\n    \"lng\": 126.5481,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": null,\n    \"population\": 2396000.0,\n    \"id\": 1156646448\n  },\n  {\n    \"city\": \"Encheng\",\n    \"city_ascii\": \"Encheng\",\n    \"lat\": 22.1879,\n    \"lng\": 112.3131,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 509700.0,\n    \"id\": 1156653230\n  },\n  {\n    \"city\": \"Suining\",\n    \"city_ascii\": \"Suining\",\n    \"lat\": 30.5098,\n    \"lng\": 105.5737,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 3252619.0,\n    \"id\": 1156655650\n  },\n  {\n    \"city\": \"Dingzhou\",\n    \"city_ascii\": \"Dingzhou\",\n    \"lat\": 38.5158,\n    \"lng\": 114.9845,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 1165182.0,\n    \"id\": 1156656582\n  },\n  {\n    \"city\": \"Xunyang\",\n    \"city_ascii\": \"Xunyang\",\n    \"lat\": 32.8357,\n    \"lng\": 109.359,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": null,\n    \"population\": 426677.0,\n    \"id\": 1156656651\n  },\n  {\n    \"city\": \"Jiaji\",\n    \"city_ascii\": \"Jiaji\",\n    \"lat\": 19.2431,\n    \"lng\": 110.4642,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hainan\",\n    \"capital\": \"minor\",\n    \"population\": 515700.0,\n    \"id\": 1156658217\n  },\n  {\n    \"city\": \"Zhongshu\",\n    \"city_ascii\": \"Zhongshu\",\n    \"lat\": 27.8116,\n    \"lng\": 106.4133,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": null,\n    \"population\": 679624.0,\n    \"id\": 1156658422\n  },\n  {\n    \"city\": \"Panshi\",\n    \"city_ascii\": \"Panshi\",\n    \"lat\": 42.9392,\n    \"lng\": 126.0561,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": null,\n    \"population\": 370238.0,\n    \"id\": 1156659612\n  },\n  {\n    \"city\": \"Jin’e\",\n    \"city_ascii\": \"Jin'e\",\n    \"lat\": 29.3395,\n    \"lng\": 105.2868,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 633210.0,\n    \"id\": 1156661253\n  },\n  {\n    \"city\": \"Huaiyin\",\n    \"city_ascii\": \"Huaiyin\",\n    \"lat\": 33.5819,\n    \"lng\": 119.028,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": null,\n    \"population\": 1264000.0,\n    \"id\": 1156662372\n  },\n  {\n    \"city\": \"Heyuan\",\n    \"city_ascii\": \"Heyuan\",\n    \"lat\": 23.7503,\n    \"lng\": 114.6923,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 3093900.0,\n    \"id\": 1156665165\n  },\n  {\n    \"city\": \"Yakeshi\",\n    \"city_ascii\": \"Yakeshi\",\n    \"lat\": 49.2842,\n    \"lng\": 120.7283,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Inner Mongolia\",\n    \"capital\": \"minor\",\n    \"population\": 352173.0,\n    \"id\": 1156666223\n  },\n  {\n    \"city\": \"Shaoyang\",\n    \"city_ascii\": \"Shaoyang\",\n    \"lat\": 32.9387,\n    \"lng\": 119.8404,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 1253548.0,\n    \"id\": 1156668366\n  },\n  {\n    \"city\": \"Chaohucun\",\n    \"city_ascii\": \"Chaohucun\",\n    \"lat\": 31.6783,\n    \"lng\": 117.7353,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": null,\n    \"population\": 782000.0,\n    \"id\": 1156671495\n  },\n  {\n    \"city\": \"Shengli\",\n    \"city_ascii\": \"Shengli\",\n    \"lat\": 37.45,\n    \"lng\": 118.4667,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 2193518.0,\n    \"id\": 1156672254\n  },\n  {\n    \"city\": \"Gaomi\",\n    \"city_ascii\": \"Gaomi\",\n    \"lat\": 36.3833,\n    \"lng\": 119.75,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 868715.0,\n    \"id\": 1156673331\n  },\n  {\n    \"city\": \"Qionghu\",\n    \"city_ascii\": \"Qionghu\",\n    \"lat\": 28.8417,\n    \"lng\": 112.3595,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 667104.0,\n    \"id\": 1156678111\n  },\n  {\n    \"city\": \"Gulou\",\n    \"city_ascii\": \"Gulou\",\n    \"lat\": 26.0865,\n    \"lng\": 119.298,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 2606000.0,\n    \"id\": 1156680279\n  },\n  {\n    \"city\": \"Yuxi\",\n    \"city_ascii\": \"Yuxi\",\n    \"lat\": 24.3495,\n    \"lng\": 102.5432,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": \"minor\",\n    \"population\": 2386000.0,\n    \"id\": 1156682309\n  },\n  {\n    \"city\": \"Lanxi\",\n    \"city_ascii\": \"Lanxi\",\n    \"lat\": 29.2167,\n    \"lng\": 119.4722,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 560514.0,\n    \"id\": 1156686465\n  },\n  {\n    \"city\": \"Kaifeng Chengguanzhen\",\n    \"city_ascii\": \"Kaifeng Chengguanzhen\",\n    \"lat\": 34.8519,\n    \"lng\": 114.3481,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 872000.0,\n    \"id\": 1156686574\n  },\n  {\n    \"city\": \"Qingnian\",\n    \"city_ascii\": \"Qingnian\",\n    \"lat\": 36.8494,\n    \"lng\": 115.7061,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 760781.0,\n    \"id\": 1156689964\n  },\n  {\n    \"city\": \"Shahe\",\n    \"city_ascii\": \"Shahe\",\n    \"lat\": 36.8622,\n    \"lng\": 114.502,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 486329.0,\n    \"id\": 1156690538\n  },\n  {\n    \"city\": \"Miluo Chengguanzhen\",\n    \"city_ascii\": \"Miluo Chengguanzhen\",\n    \"lat\": 28.8049,\n    \"lng\": 113.0745,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 692080.0,\n    \"id\": 1156690651\n  },\n  {\n    \"city\": \"Tanbei\",\n    \"city_ascii\": \"Tanbei\",\n    \"lat\": 35.0907,\n    \"lng\": 112.9317,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 447701.0,\n    \"id\": 1156690688\n  },\n  {\n    \"city\": \"Yongzhou\",\n    \"city_ascii\": \"Yongzhou\",\n    \"lat\": 26.4515,\n    \"lng\": 111.5953,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 5452100.0,\n    \"id\": 1156694479\n  },\n  {\n    \"city\": \"Gongzhuling\",\n    \"city_ascii\": \"Gongzhuling\",\n    \"lat\": 43.5036,\n    \"lng\": 124.8088,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 1092692.0,\n    \"id\": 1156696810\n  },\n  {\n    \"city\": \"Hengyang\",\n    \"city_ascii\": \"Hengyang\",\n    \"lat\": 26.8968,\n    \"lng\": 112.5857,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": null,\n    \"population\": 7243400.0,\n    \"id\": 1156696884\n  },\n  {\n    \"city\": \"Cangzhou\",\n    \"city_ascii\": \"Cangzhou\",\n    \"lat\": 38.3037,\n    \"lng\": 116.8452,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 7544300.0,\n    \"id\": 1156698069\n  },\n  {\n    \"city\": \"Wuxi\",\n    \"city_ascii\": \"Wuxi\",\n    \"lat\": 26.5895,\n    \"lng\": 111.8481,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 853197.0,\n    \"id\": 1156698595\n  },\n  {\n    \"city\": \"Leping\",\n    \"city_ascii\": \"Leping\",\n    \"lat\": 28.9632,\n    \"lng\": 117.1203,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": \"minor\",\n    \"population\": 852800.0,\n    \"id\": 1156705082\n  },\n  {\n    \"city\": \"Yuncheng\",\n    \"city_ascii\": \"Yuncheng\",\n    \"lat\": 35.0304,\n    \"lng\": 110.998,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": null,\n    \"population\": 5134779.0,\n    \"id\": 1156705644\n  },\n  {\n    \"city\": \"Xingcheng\",\n    \"city_ascii\": \"Xingcheng\",\n    \"lat\": 40.6189,\n    \"lng\": 120.7205,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 546176.0,\n    \"id\": 1156705922\n  },\n  {\n    \"city\": \"Chaoyang\",\n    \"city_ascii\": \"Chaoyang\",\n    \"lat\": 41.5757,\n    \"lng\": 120.4486,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 3044641.0,\n    \"id\": 1156706927\n  },\n  {\n    \"city\": \"Pinghu\",\n    \"city_ascii\": \"Pinghu\",\n    \"lat\": 30.7005,\n    \"lng\": 121.0104,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 671834.0,\n    \"id\": 1156720536\n  },\n  {\n    \"city\": \"Zhuhai\",\n    \"city_ascii\": \"Zhuhai\",\n    \"lat\": 22.2769,\n    \"lng\": 113.5678,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 2439585.0,\n    \"id\": 1156722242\n  },\n  {\n    \"city\": \"Wu’an\",\n    \"city_ascii\": \"Wu'an\",\n    \"lat\": 36.6941,\n    \"lng\": 114.1847,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 819000.0,\n    \"id\": 1156729960\n  },\n  {\n    \"city\": \"Helixi\",\n    \"city_ascii\": \"Helixi\",\n    \"lat\": 30.6267,\n    \"lng\": 118.9861,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 376857.0,\n    \"id\": 1156734041\n  },\n  {\n    \"city\": \"Pingdingshan\",\n    \"city_ascii\": \"Pingdingshan\",\n    \"lat\": 33.735,\n    \"lng\": 113.2999,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 4904701.0,\n    \"id\": 1156735124\n  },\n  {\n    \"city\": \"Foshan\",\n    \"city_ascii\": \"Foshan\",\n    \"lat\": 23.0292,\n    \"lng\": 113.1056,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 9498863.0,\n    \"id\": 1156738403\n  },\n  {\n    \"city\": \"Yicheng\",\n    \"city_ascii\": \"Yicheng\",\n    \"lat\": 31.7117,\n    \"lng\": 112.2551,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"minor\",\n    \"population\": 512530.0,\n    \"id\": 1156742818\n  },\n  {\n    \"city\": \"Qujing\",\n    \"city_ascii\": \"Qujing\",\n    \"lat\": 25.5102,\n    \"lng\": 103.8029,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": null,\n    \"population\": 6155400.0,\n    \"id\": 1156747998\n  },\n  {\n    \"city\": \"Yingchuan\",\n    \"city_ascii\": \"Yingchuan\",\n    \"lat\": 34.1511,\n    \"lng\": 113.4733,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 1131896.0,\n    \"id\": 1156748426\n  },\n  {\n    \"city\": \"Jiaozhou\",\n    \"city_ascii\": \"Jiaozhou\",\n    \"lat\": 36.2481,\n    \"lng\": 119.9625,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 900500.0,\n    \"id\": 1156752602\n  },\n  {\n    \"city\": \"Puning\",\n    \"city_ascii\": \"Puning\",\n    \"lat\": 23.2993,\n    \"lng\": 116.1586,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": null,\n    \"population\": 2118200.0,\n    \"id\": 1156756494\n  },\n  {\n    \"city\": \"Zunhua\",\n    \"city_ascii\": \"Zunhua\",\n    \"lat\": 40.1881,\n    \"lng\": 117.9593,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": \"minor\",\n    \"population\": 737011.0,\n    \"id\": 1156756935\n  },\n  {\n    \"city\": \"Yichun\",\n    \"city_ascii\": \"Yichun\",\n    \"lat\": 47.7235,\n    \"lng\": 128.8893,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 1148126.0,\n    \"id\": 1156757274\n  },\n  {\n    \"city\": \"Zhengjiatun\",\n    \"city_ascii\": \"Zhengjiatun\",\n    \"lat\": 43.513,\n    \"lng\": 123.5003,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 419529.0,\n    \"id\": 1156759747\n  },\n  {\n    \"city\": \"Wuwei\",\n    \"city_ascii\": \"Wuwei\",\n    \"lat\": 37.9278,\n    \"lng\": 102.6329,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": \"minor\",\n    \"population\": 1815059.0,\n    \"id\": 1156760291\n  },\n  {\n    \"city\": \"Xintai\",\n    \"city_ascii\": \"Xintai\",\n    \"lat\": 35.91,\n    \"lng\": 117.78,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 1315942.0,\n    \"id\": 1156761230\n  },\n  {\n    \"city\": \"Nanchong\",\n    \"city_ascii\": \"Nanchong\",\n    \"lat\": 30.7991,\n    \"lng\": 106.0784,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 6278614.0,\n    \"id\": 1156762337\n  },\n  {\n    \"city\": \"Xiaoxita\",\n    \"city_ascii\": \"Xiaoxita\",\n    \"lat\": 30.7083,\n    \"lng\": 111.2803,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": \"minor\",\n    \"population\": 4137900.0,\n    \"id\": 1156764447\n  },\n  {\n    \"city\": \"Suoluntun\",\n    \"city_ascii\": \"Suoluntun\",\n    \"lat\": 45.2279,\n    \"lng\": 124.8432,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": null,\n    \"population\": 495900.0,\n    \"id\": 1156764587\n  },\n  {\n    \"city\": \"Tieli\",\n    \"city_ascii\": \"Tieli\",\n    \"lat\": 46.9838,\n    \"lng\": 128.04,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 390000.0,\n    \"id\": 1156769379\n  },\n  {\n    \"city\": \"Zhijiang\",\n    \"city_ascii\": \"Zhijiang\",\n    \"lat\": 30.4271,\n    \"lng\": 111.7506,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 495995.0,\n    \"id\": 1156769646\n  },\n  {\n    \"city\": \"Tianchang\",\n    \"city_ascii\": \"Tianchang\",\n    \"lat\": 32.6853,\n    \"lng\": 119.0041,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 602840.0,\n    \"id\": 1156770851\n  },\n  {\n    \"city\": \"Qiqihar\",\n    \"city_ascii\": \"Qiqihar\",\n    \"lat\": 47.3398,\n    \"lng\": 123.9512,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 5367003.0,\n    \"id\": 1156775905\n  },\n  {\n    \"city\": \"Gaozhou\",\n    \"city_ascii\": \"Gaozhou\",\n    \"lat\": 21.9135,\n    \"lng\": 110.8481,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 1414100.0,\n    \"id\": 1156785303\n  },\n  {\n    \"city\": \"Yangchun\",\n    \"city_ascii\": \"Yangchun\",\n    \"lat\": 22.1717,\n    \"lng\": 111.7846,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": null,\n    \"population\": 891800.0,\n    \"id\": 1156787307\n  },\n  {\n    \"city\": \"Shouguang\",\n    \"city_ascii\": \"Shouguang\",\n    \"lat\": 36.8833,\n    \"lng\": 118.7333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 1039205.0,\n    \"id\": 1156787809\n  },\n  {\n    \"city\": \"Laohekou\",\n    \"city_ascii\": \"Laohekou\",\n    \"lat\": 32.3849,\n    \"lng\": 111.6695,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 471482.0,\n    \"id\": 1156791804\n  },\n  {\n    \"city\": \"Rongjiawan\",\n    \"city_ascii\": \"Rongjiawan\",\n    \"lat\": 29.1409,\n    \"lng\": 113.1087,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"minor\",\n    \"population\": 826000.0,\n    \"id\": 1156795164\n  },\n  {\n    \"city\": \"Zaozhuang\",\n    \"city_ascii\": \"Zaozhuang\",\n    \"lat\": 34.8667,\n    \"lng\": 117.55,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 3729140.0,\n    \"id\": 1156796454\n  },\n  {\n    \"city\": \"Huazhou\",\n    \"city_ascii\": \"Huazhou\",\n    \"lat\": 32.6832,\n    \"lng\": 112.079,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 1468061.0,\n    \"id\": 1156796734\n  },\n  {\n    \"city\": \"Zhangjiakou\",\n    \"city_ascii\": \"Zhangjiakou\",\n    \"lat\": 40.8108,\n    \"lng\": 114.8811,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": \"minor\",\n    \"population\": 4345485.0,\n    \"id\": 1156800221\n  },\n  {\n    \"city\": \"Hengshui\",\n    \"city_ascii\": \"Hengshui\",\n    \"lat\": 37.7348,\n    \"lng\": 115.686,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 4472000.0,\n    \"id\": 1156803028\n  },\n  {\n    \"city\": \"Tongren\",\n    \"city_ascii\": \"Tongren\",\n    \"lat\": 27.7233,\n    \"lng\": 109.1885,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": null,\n    \"population\": 3168800.0,\n    \"id\": 1156803442\n  },\n  {\n    \"city\": \"Hailun\",\n    \"city_ascii\": \"Hailun\",\n    \"lat\": 47.4585,\n    \"lng\": 126.9632,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 850000.0,\n    \"id\": 1156804488\n  },\n  {\n    \"city\": \"Shangqiu\",\n    \"city_ascii\": \"Shangqiu\",\n    \"lat\": 34.4259,\n    \"lng\": 115.6467,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 7816831.0,\n    \"id\": 1156805441\n  },\n  {\n    \"city\": \"Putian\",\n    \"city_ascii\": \"Putian\",\n    \"lat\": 25.4394,\n    \"lng\": 119.0103,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 3210714.0,\n    \"id\": 1156811601\n  },\n  {\n    \"city\": \"Jiaojiangcun\",\n    \"city_ascii\": \"Jiaojiangcun\",\n    \"lat\": 28.6804,\n    \"lng\": 121.45,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 471500.0,\n    \"id\": 1156812073\n  },\n  {\n    \"city\": \"Yucheng\",\n    \"city_ascii\": \"Yucheng\",\n    \"lat\": 29.9888,\n    \"lng\": 103.0007,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 1507258.0,\n    \"id\": 1156817119\n  },\n  {\n    \"city\": \"Zouping\",\n    \"city_ascii\": \"Zouping\",\n    \"lat\": 36.8625,\n    \"lng\": 117.7424,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 774517.0,\n    \"id\": 1156817518\n  },\n  {\n    \"city\": \"Guyuan\",\n    \"city_ascii\": \"Guyuan\",\n    \"lat\": 36.008,\n    \"lng\": 106.2782,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Ningxia\",\n    \"capital\": null,\n    \"population\": 1426000.0,\n    \"id\": 1156817541\n  },\n  {\n    \"city\": \"Yangzhou\",\n    \"city_ascii\": \"Yangzhou\",\n    \"lat\": 32.3912,\n    \"lng\": 119.4363,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": null,\n    \"population\": 4559797.0,\n    \"id\": 1156818601\n  },\n  {\n    \"city\": \"Dayan\",\n    \"city_ascii\": \"Dayan\",\n    \"lat\": 26.8808,\n    \"lng\": 100.2208,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": null,\n    \"population\": 1296000.0,\n    \"id\": 1156828380\n  },\n  {\n    \"city\": \"Quanzhou\",\n    \"city_ascii\": \"Quanzhou\",\n    \"lat\": 24.9139,\n    \"lng\": 118.5858,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 8782285.0,\n    \"id\": 1156829655\n  },\n  {\n    \"city\": \"Ganzhou\",\n    \"city_ascii\": \"Ganzhou\",\n    \"lat\": 25.8292,\n    \"lng\": 114.9336,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": \"minor\",\n    \"population\": 8970014.0,\n    \"id\": 1156832475\n  },\n  {\n    \"city\": \"Tengyue\",\n    \"city_ascii\": \"Tengyue\",\n    \"lat\": 25.0208,\n    \"lng\": 98.4972,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": \"minor\",\n    \"population\": 644765.0,\n    \"id\": 1156832866\n  },\n  {\n    \"city\": \"Dazhou\",\n    \"city_ascii\": \"Dazhou\",\n    \"lat\": 31.2152,\n    \"lng\": 107.4947,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 5468097.0,\n    \"id\": 1156834076\n  },\n  {\n    \"city\": \"Lingbao Chengguanzhen\",\n    \"city_ascii\": \"Lingbao Chengguanzhen\",\n    \"lat\": 34.5221,\n    \"lng\": 110.8786,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 656571.0,\n    \"id\": 1156837145\n  },\n  {\n    \"city\": \"Songzi\",\n    \"city_ascii\": \"Songzi\",\n    \"lat\": 30.1772,\n    \"lng\": 111.7732,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 765911.0,\n    \"id\": 1156837705\n  },\n  {\n    \"city\": \"Dali\",\n    \"city_ascii\": \"Dali\",\n    \"lat\": 25.6808,\n    \"lng\": 100.3003,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": null,\n    \"population\": 771128.0,\n    \"id\": 1156840276\n  },\n  {\n    \"city\": \"Yongcheng\",\n    \"city_ascii\": \"Yongcheng\",\n    \"lat\": 33.9317,\n    \"lng\": 116.4459,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": null,\n    \"population\": 1240382.0,\n    \"id\": 1156841802\n  },\n  {\n    \"city\": \"Ma’anshan\",\n    \"city_ascii\": \"Ma'anshan\",\n    \"lat\": 31.6858,\n    \"lng\": 118.5101,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": \"minor\",\n    \"population\": 2202899.0,\n    \"id\": 1156847452\n  },\n  {\n    \"city\": \"Tongchuan\",\n    \"city_ascii\": \"Tongchuan\",\n    \"lat\": 34.9057,\n    \"lng\": 108.9422,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": \"minor\",\n    \"population\": 834437.0,\n    \"id\": 1156849608\n  },\n  {\n    \"city\": \"Fushun\",\n    \"city_ascii\": \"Fushun\",\n    \"lat\": 41.8708,\n    \"lng\": 123.8917,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 2024000.0,\n    \"id\": 1156857743\n  },\n  {\n    \"city\": \"Lishui\",\n    \"city_ascii\": \"Lishui\",\n    \"lat\": 28.45,\n    \"lng\": 119.9167,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 2507396.0,\n    \"id\": 1156858793\n  },\n  {\n    \"city\": \"Leizhou\",\n    \"city_ascii\": \"Leizhou\",\n    \"lat\": 20.9147,\n    \"lng\": 110.0806,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 1494700.0,\n    \"id\": 1156863840\n  },\n  {\n    \"city\": \"Longzhou\",\n    \"city_ascii\": \"Longzhou\",\n    \"lat\": 30.32,\n    \"lng\": 112.23,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 520000.0,\n    \"id\": 1156863928\n  },\n  {\n    \"city\": \"Mingguang\",\n    \"city_ascii\": \"Mingguang\",\n    \"lat\": 32.7816,\n    \"lng\": 117.9899,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": null,\n    \"population\": 532732.0,\n    \"id\": 1156864248\n  },\n  {\n    \"city\": \"Chengguan\",\n    \"city_ascii\": \"Chengguan\",\n    \"lat\": 35.5256,\n    \"lng\": 113.6976,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 740435.0,\n    \"id\": 1156866870\n  },\n  {\n    \"city\": \"Suzhou\",\n    \"city_ascii\": \"Suzhou\",\n    \"lat\": 33.6333,\n    \"lng\": 116.9683,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": null,\n    \"population\": 5352924.0,\n    \"id\": 1156871297\n  },\n  {\n    \"city\": \"Qingzhou\",\n    \"city_ascii\": \"Qingzhou\",\n    \"lat\": 36.6967,\n    \"lng\": 118.4797,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 914047.0,\n    \"id\": 1156874864\n  },\n  {\n    \"city\": \"Taihecun\",\n    \"city_ascii\": \"Taihecun\",\n    \"lat\": 45.768,\n    \"lng\": 131.0063,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Heilongjiang\",\n    \"capital\": \"minor\",\n    \"population\": 920471.0,\n    \"id\": 1156875484\n  },\n  {\n    \"city\": \"Huainan\",\n    \"city_ascii\": \"Huainan\",\n    \"lat\": 32.4831,\n    \"lng\": 117.0164,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Anhui\",\n    \"capital\": null,\n    \"population\": 2333896.0,\n    \"id\": 1156877299\n  },\n  {\n    \"city\": \"Chengtangcun\",\n    \"city_ascii\": \"Chengtangcun\",\n    \"lat\": 35.0833,\n    \"lng\": 117.15,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 1603659.0,\n    \"id\": 1156883901\n  },\n  {\n    \"city\": \"Karamay\",\n    \"city_ascii\": \"Karamay\",\n    \"lat\": 45.5799,\n    \"lng\": 84.8892,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"minor\",\n    \"population\": 391008.0,\n    \"id\": 1156892128\n  },\n  {\n    \"city\": \"Shaoxing\",\n    \"city_ascii\": \"Shaoxing\",\n    \"lat\": 30.0,\n    \"lng\": 120.5833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": \"minor\",\n    \"population\": 2521964.0,\n    \"id\": 1156893449\n  },\n  {\n    \"city\": \"Fuqing\",\n    \"city_ascii\": \"Fuqing\",\n    \"lat\": 25.7232,\n    \"lng\": 119.3735,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 1390487.0,\n    \"id\": 1156893569\n  },\n  {\n    \"city\": \"Kuqa\",\n    \"city_ascii\": \"Kuqa\",\n    \"lat\": 41.7156,\n    \"lng\": 82.9322,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"minor\",\n    \"population\": 462588.0,\n    \"id\": 1156894895\n  },\n  {\n    \"city\": \"Guigang\",\n    \"city_ascii\": \"Guigang\",\n    \"lat\": 23.0961,\n    \"lng\": 109.6092,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 4409200.0,\n    \"id\": 1156895251\n  },\n  {\n    \"city\": \"Jurong\",\n    \"city_ascii\": \"Jurong\",\n    \"lat\": 31.9579,\n    \"lng\": 119.1595,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": null,\n    \"population\": 617706.0,\n    \"id\": 1156897463\n  },\n  {\n    \"city\": \"Dehui\",\n    \"city_ascii\": \"Dehui\",\n    \"lat\": 44.5333,\n    \"lng\": 125.7,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": null,\n    \"population\": 839786.0,\n    \"id\": 1156898134\n  },\n  {\n    \"city\": \"Xiping\",\n    \"city_ascii\": \"Xiping\",\n    \"lat\": 40.082,\n    \"lng\": 113.2981,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": \"minor\",\n    \"population\": 1873000.0,\n    \"id\": 1156898522\n  },\n  {\n    \"city\": \"Yueqing\",\n    \"city_ascii\": \"Yueqing\",\n    \"lat\": 28.1188,\n    \"lng\": 120.9621,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 488980.0,\n    \"id\": 1156900058\n  },\n  {\n    \"city\": \"Yulin\",\n    \"city_ascii\": \"Yulin\",\n    \"lat\": 22.6293,\n    \"lng\": 110.1507,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 5849700.0,\n    \"id\": 1156901312\n  },\n  {\n    \"city\": \"Dadukou\",\n    \"city_ascii\": \"Dadukou\",\n    \"lat\": 26.5849,\n    \"lng\": 101.7149,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 1214121.0,\n    \"id\": 1156901342\n  },\n  {\n    \"city\": \"Changshu\",\n    \"city_ascii\": \"Changshu\",\n    \"lat\": 31.65,\n    \"lng\": 120.7333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": null,\n    \"population\": 1677050.0,\n    \"id\": 1156901538\n  },\n  {\n    \"city\": \"Anshan\",\n    \"city_ascii\": \"Anshan\",\n    \"lat\": 41.1066,\n    \"lng\": 122.9895,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Liaoning\",\n    \"capital\": null,\n    \"population\": 3645884.0,\n    \"id\": 1156901825\n  },\n  {\n    \"city\": \"Weinan\",\n    \"city_ascii\": \"Weinan\",\n    \"lat\": 34.4996,\n    \"lng\": 109.4684,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shaanxi\",\n    \"capital\": \"minor\",\n    \"population\": 5286077.0,\n    \"id\": 1156903687\n  },\n  {\n    \"city\": \"Tangshan\",\n    \"city_ascii\": \"Tangshan\",\n    \"lat\": 39.6292,\n    \"lng\": 118.1742,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 3399231.0,\n    \"id\": 1156904299\n  },\n  {\n    \"city\": \"Hongzhai\",\n    \"city_ascii\": \"Hongzhai\",\n    \"lat\": 34.9857,\n    \"lng\": 104.5446,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": null,\n    \"population\": 355037.0,\n    \"id\": 1156905289\n  },\n  {\n    \"city\": \"Ningde\",\n    \"city_ascii\": \"Ningde\",\n    \"lat\": 26.6617,\n    \"lng\": 119.5228,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 2910000.0,\n    \"id\": 1156909802\n  },\n  {\n    \"city\": \"Xiaoyi\",\n    \"city_ascii\": \"Xiaoyi\",\n    \"lat\": 37.1449,\n    \"lng\": 111.7718,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shanxi\",\n    \"capital\": null,\n    \"population\": 468770.0,\n    \"id\": 1156910270\n  },\n  {\n    \"city\": \"Nada\",\n    \"city_ascii\": \"Nada\",\n    \"lat\": 19.5,\n    \"lng\": 109.5833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hainan\",\n    \"capital\": \"minor\",\n    \"population\": 977700.0,\n    \"id\": 1156911678\n  },\n  {\n    \"city\": \"Weifang\",\n    \"city_ascii\": \"Weifang\",\n    \"lat\": 36.7167,\n    \"lng\": 119.1,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 2636154.0,\n    \"id\": 1156912965\n  },\n  {\n    \"city\": \"Xingcheng\",\n    \"city_ascii\": \"Xingcheng\",\n    \"lat\": 24.1681,\n    \"lng\": 115.6669,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 993000.0,\n    \"id\": 1156913008\n  },\n  {\n    \"city\": \"Fuzhou\",\n    \"city_ascii\": \"Fuzhou\",\n    \"lat\": 27.9814,\n    \"lng\": 116.3577,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": null,\n    \"population\": 4047200.0,\n    \"id\": 1156915325\n  },\n  {\n    \"city\": \"Qianxi\",\n    \"city_ascii\": \"Qianxi\",\n    \"lat\": 27.0284,\n    \"lng\": 106.0327,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": null,\n    \"population\": 695947.0,\n    \"id\": 1156919716\n  },\n  {\n    \"city\": \"Shenzhou\",\n    \"city_ascii\": \"Shenzhou\",\n    \"lat\": 38.0005,\n    \"lng\": 115.5541,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 566087.0,\n    \"id\": 1156921843\n  },\n  {\n    \"city\": \"Zhaotong\",\n    \"city_ascii\": \"Zhaotong\",\n    \"lat\": 27.3328,\n    \"lng\": 103.7144,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Yunnan\",\n    \"capital\": null,\n    \"population\": 5591000.0,\n    \"id\": 1156924687\n  },\n  {\n    \"city\": \"Laibin\",\n    \"city_ascii\": \"Laibin\",\n    \"lat\": 23.7333,\n    \"lng\": 109.2333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 2233900.0,\n    \"id\": 1156925734\n  },\n  {\n    \"city\": \"Nanping\",\n    \"city_ascii\": \"Nanping\",\n    \"lat\": 26.6448,\n    \"lng\": 118.1728,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Fujian\",\n    \"capital\": \"minor\",\n    \"population\": 2690000.0,\n    \"id\": 1156927445\n  },\n  {\n    \"city\": \"Langzhong\",\n    \"city_ascii\": \"Langzhong\",\n    \"lat\": 31.5504,\n    \"lng\": 105.9938,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Sichuan\",\n    \"capital\": \"minor\",\n    \"population\": 728935.0,\n    \"id\": 1156930148\n  },\n  {\n    \"city\": \"Guiyang\",\n    \"city_ascii\": \"Guiyang\",\n    \"lat\": 26.5794,\n    \"lng\": 106.7078,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guizhou\",\n    \"capital\": \"admin\",\n    \"population\": 3299724.0,\n    \"id\": 1156932620\n  },\n  {\n    \"city\": \"Yantai\",\n    \"city_ascii\": \"Yantai\",\n    \"lat\": 37.3997,\n    \"lng\": 121.2664,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 2511053.0,\n    \"id\": 1156932948\n  },\n  {\n    \"city\": \"Licheng\",\n    \"city_ascii\": \"Licheng\",\n    \"lat\": 31.4174,\n    \"lng\": 119.4786,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 749522.0,\n    \"id\": 1156933354\n  },\n  {\n    \"city\": \"Zhenjiang\",\n    \"city_ascii\": \"Zhenjiang\",\n    \"lat\": 32.2109,\n    \"lng\": 119.4551,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 3210418.0,\n    \"id\": 1156934125\n  },\n  {\n    \"city\": \"Mizhou\",\n    \"city_ascii\": \"Mizhou\",\n    \"lat\": 35.99,\n    \"lng\": 119.3801,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"minor\",\n    \"population\": 1060000.0,\n    \"id\": 1156935002\n  },\n  {\n    \"city\": \"Chongqing\",\n    \"city_ascii\": \"Chongqing\",\n    \"lat\": 29.55,\n    \"lng\": 106.5069,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Chongqing\",\n    \"capital\": \"admin\",\n    \"population\": 12135000.0,\n    \"id\": 1156936556\n  },\n  {\n    \"city\": \"Xinyi\",\n    \"city_ascii\": \"Xinyi\",\n    \"lat\": 22.3559,\n    \"lng\": 110.9369,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": null,\n    \"population\": 1013900.0,\n    \"id\": 1156936644\n  },\n  {\n    \"city\": \"Shanwei\",\n    \"city_ascii\": \"Shanwei\",\n    \"lat\": 22.7664,\n    \"lng\": 115.3331,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": \"minor\",\n    \"population\": 2993600.0,\n    \"id\": 1156939010\n  },\n  {\n    \"city\": \"Renqiu\",\n    \"city_ascii\": \"Renqiu\",\n    \"lat\": 38.7094,\n    \"lng\": 116.1008,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": null,\n    \"population\": 822455.0,\n    \"id\": 1156943939\n  },\n  {\n    \"city\": \"Lianjiang\",\n    \"city_ascii\": \"Lianjiang\",\n    \"lat\": 21.6146,\n    \"lng\": 110.2794,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangdong\",\n    \"capital\": null,\n    \"population\": 1509400.0,\n    \"id\": 1156944106\n  },\n  {\n    \"city\": \"Macheng\",\n    \"city_ascii\": \"Macheng\",\n    \"lat\": 31.1817,\n    \"lng\": 115.0189,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hubei\",\n    \"capital\": null,\n    \"population\": 849090.0,\n    \"id\": 1156949639\n  },\n  {\n    \"city\": \"Guangming\",\n    \"city_ascii\": \"Guangming\",\n    \"lat\": 45.3357,\n    \"lng\": 122.7765,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 437559.0,\n    \"id\": 1156955625\n  },\n  {\n    \"city\": \"Zhongwei\",\n    \"city_ascii\": \"Zhongwei\",\n    \"lat\": 37.5139,\n    \"lng\": 105.1884,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Ningxia\",\n    \"capital\": \"minor\",\n    \"population\": 1067336.0,\n    \"id\": 1156956616\n  },\n  {\n    \"city\": \"Handan\",\n    \"city_ascii\": \"Handan\",\n    \"lat\": 36.6116,\n    \"lng\": 114.4894,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hebei\",\n    \"capital\": \"minor\",\n    \"population\": 2708015.0,\n    \"id\": 1156957080\n  },\n  {\n    \"city\": \"Xibeijie\",\n    \"city_ascii\": \"Xibeijie\",\n    \"lat\": 39.737,\n    \"lng\": 98.5049,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Gansu\",\n    \"capital\": \"minor\",\n    \"population\": 1095947.0,\n    \"id\": 1156960560\n  },\n  {\n    \"city\": \"Baishan\",\n    \"city_ascii\": \"Baishan\",\n    \"lat\": 41.9377,\n    \"lng\": 126.4179,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 1296127.0,\n    \"id\": 1156960624\n  },\n  {\n    \"city\": \"Changsha\",\n    \"city_ascii\": \"Changsha\",\n    \"lat\": 28.1987,\n    \"lng\": 112.9709,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hunan\",\n    \"capital\": \"admin\",\n    \"population\": 4766296.0,\n    \"id\": 1156961497\n  },\n  {\n    \"city\": \"Korla\",\n    \"city_ascii\": \"Korla\",\n    \"lat\": 41.7259,\n    \"lng\": 86.1746,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Xinjiang\",\n    \"capital\": \"minor\",\n    \"population\": 770000.0,\n    \"id\": 1156965620\n  },\n  {\n    \"city\": \"Shuangqiao\",\n    \"city_ascii\": \"Shuangqiao\",\n    \"lat\": 35.0833,\n    \"lng\": 112.5833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Henan\",\n    \"capital\": \"minor\",\n    \"population\": 733000.0,\n    \"id\": 1156968311\n  },\n  {\n    \"city\": \"Jinan\",\n    \"city_ascii\": \"Jinan\",\n    \"lat\": 36.6667,\n    \"lng\": 116.9833,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": \"admin\",\n    \"population\": 5606374.0,\n    \"id\": 1156972469\n  },\n  {\n    \"city\": \"Laixi\",\n    \"city_ascii\": \"Laixi\",\n    \"lat\": 36.8667,\n    \"lng\": 120.5333,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Shandong\",\n    \"capital\": null,\n    \"population\": 762900.0,\n    \"id\": 1156973102\n  },\n  {\n    \"city\": \"Baicheng\",\n    \"city_ascii\": \"Baicheng\",\n    \"lat\": 23.901,\n    \"lng\": 106.6194,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Guangxi\",\n    \"capital\": \"minor\",\n    \"population\": 3669400.0,\n    \"id\": 1156981113\n  },\n  {\n    \"city\": \"Wencheng\",\n    \"city_ascii\": \"Wencheng\",\n    \"lat\": 19.6167,\n    \"lng\": 110.75,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Hainan\",\n    \"capital\": \"minor\",\n    \"population\": 568900.0,\n    \"id\": 1156985313\n  },\n  {\n    \"city\": \"Baisha\",\n    \"city_ascii\": \"Baisha\",\n    \"lat\": 29.4774,\n    \"lng\": 119.2853,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 446000.0,\n    \"id\": 1156988315\n  },\n  {\n    \"city\": \"Shulan\",\n    \"city_ascii\": \"Shulan\",\n    \"lat\": 44.4079,\n    \"lng\": 126.9429,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jilin\",\n    \"capital\": \"minor\",\n    \"population\": 663403.0,\n    \"id\": 1156989733\n  },\n  {\n    \"city\": \"Rui’an\",\n    \"city_ascii\": \"Rui'an\",\n    \"lat\": 27.778,\n    \"lng\": 120.6526,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Zhejiang\",\n    \"capital\": null,\n    \"population\": 1424667.0,\n    \"id\": 1156993705\n  },\n  {\n    \"city\": \"Yancheng\",\n    \"city_ascii\": \"Yancheng\",\n    \"lat\": 33.3936,\n    \"lng\": 120.1339,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangsu\",\n    \"capital\": \"minor\",\n    \"population\": 7260240.0,\n    \"id\": 1156995410\n  },\n  {\n    \"city\": \"Zhangshu\",\n    \"city_ascii\": \"Zhangshu\",\n    \"lat\": 28.0667,\n    \"lng\": 115.5375,\n    \"country\": \"China\",\n    \"iso2\": \"CN\",\n    \"iso3\": \"CHN\",\n    \"admin_name\": \"Jiangxi\",\n    \"capital\": null,\n    \"population\": 610424.0,\n    \"id\": 1156996913\n  },\n  {\n    \"city\": \"Zhongli\",\n    \"city_ascii\": \"Zhongli\",\n    \"lat\": 24.965,\n    \"lng\": 121.2168,\n    \"country\": \"Taiwan\",\n    \"iso2\": \"TW\",\n    \"iso3\": \"TWN\",\n    \"admin_name\": \"Taoyuan\",\n    \"capital\": null,\n    \"population\": 1632616.0,\n    \"id\": 1158025380\n  },\n  {\n    \"city\": \"Tainan\",\n    \"city_ascii\": \"Tainan\",\n    \"lat\": 22.9833,\n    \"lng\": 120.1833,\n    \"country\": \"Taiwan\",\n    \"iso2\": \"TW\",\n    \"iso3\": \"TWN\",\n    \"admin_name\": \"Tainan\",\n    \"capital\": \"admin\",\n    \"population\": 1874686.0,\n    \"id\": 1158061376\n  },\n  {\n    \"city\": \"Taoyuan District\",\n    \"city_ascii\": \"Taoyuan District\",\n    \"lat\": 24.9913,\n    \"lng\": 121.3143,\n    \"country\": \"Taiwan\",\n    \"iso2\": \"TW\",\n    \"iso3\": \"TWN\",\n    \"admin_name\": \"Taoyuan\",\n    \"capital\": \"admin\",\n    \"population\": 443273.0,\n    \"id\": 1158127875\n  },\n  {\n    \"city\": \"Pingtung\",\n    \"city_ascii\": \"Pingtung\",\n    \"lat\": 22.6761,\n    \"lng\": 120.4942,\n    \"country\": \"Taiwan\",\n    \"iso2\": \"TW\",\n    \"iso3\": \"TWN\",\n    \"admin_name\": \"Pingtung\",\n    \"capital\": \"admin\",\n    \"population\": 503530.0,\n    \"id\": 1158209038\n  },\n  {\n    \"city\": \"Hsinchu\",\n    \"city_ascii\": \"Hsinchu\",\n    \"lat\": 24.8167,\n    \"lng\": 120.9833,\n    \"country\": \"Taiwan\",\n    \"iso2\": \"TW\",\n    \"iso3\": \"TWN\",\n    \"admin_name\": \"Hsinchu\",\n    \"capital\": \"admin\",\n    \"population\": 499348.0,\n    \"id\": 1158276420\n  },\n  {\n    \"city\": \"Kaohsiung\",\n    \"city_ascii\": \"Kaohsiung\",\n    \"lat\": 22.615,\n    \"lng\": 120.2975,\n    \"country\": \"Taiwan\",\n    \"iso2\": \"TW\",\n    \"iso3\": \"TWN\",\n    \"admin_name\": \"Kaohsiung\",\n    \"capital\": \"admin\",\n    \"population\": 2733566.0,\n    \"id\": 1158331334\n  },\n  {\n    \"city\": \"Changhua\",\n    \"city_ascii\": \"Changhua\",\n    \"lat\": 24.0667,\n    \"lng\": 120.5333,\n    \"country\": \"Taiwan\",\n    \"iso2\": \"TW\",\n    \"iso3\": \"TWN\",\n    \"admin_name\": \"Changhua\",\n    \"capital\": \"admin\",\n    \"population\": 750000.0,\n    \"id\": 1158439005\n  },\n  {\n    \"city\": \"Taichung\",\n    \"city_ascii\": \"Taichung\",\n    \"lat\": 24.1439,\n    \"lng\": 120.6794,\n    \"country\": \"Taiwan\",\n    \"iso2\": \"TW\",\n    \"iso3\": \"TWN\",\n    \"admin_name\": \"Taichung\",\n    \"capital\": \"admin\",\n    \"population\": 3033885.0,\n    \"id\": 1158689622\n  },\n  {\n    \"city\": \"Keelung\",\n    \"city_ascii\": \"Keelung\",\n    \"lat\": 25.1333,\n    \"lng\": 121.7333,\n    \"country\": \"Taiwan\",\n    \"iso2\": \"TW\",\n    \"iso3\": \"TWN\",\n    \"admin_name\": \"Keelung\",\n    \"capital\": \"admin\",\n    \"population\": 370155.0,\n    \"id\": 1158820647\n  },\n  {\n    \"city\": \"Taipei\",\n    \"city_ascii\": \"Taipei\",\n    \"lat\": 25.0375,\n    \"lng\": 121.5625,\n    \"country\": \"Taiwan\",\n    \"iso2\": \"TW\",\n    \"iso3\": \"TWN\",\n    \"admin_name\": \"Taipei\",\n    \"capital\": \"primary\",\n    \"population\": 9078000.0,\n    \"id\": 1158881289\n  },\n  {\n    \"city\": \"Neiva\",\n    \"city_ascii\": \"Neiva\",\n    \"lat\": 2.9345,\n    \"lng\": -75.2809,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Huila\",\n    \"capital\": \"admin\",\n    \"population\": 353033.0,\n    \"id\": 1170159963\n  },\n  {\n    \"city\": \"Barranquilla\",\n    \"city_ascii\": \"Barranquilla\",\n    \"lat\": 10.9833,\n    \"lng\": -74.8019,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Atlántico\",\n    \"capital\": \"admin\",\n    \"population\": 1326588.0,\n    \"id\": 1170179113\n  },\n  {\n    \"city\": \"Ibagué\",\n    \"city_ascii\": \"Ibague\",\n    \"lat\": 4.4333,\n    \"lng\": -75.2333,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Tolima\",\n    \"capital\": \"admin\",\n    \"population\": 541101.0,\n    \"id\": 1170245063\n  },\n  {\n    \"city\": \"Buenaventura\",\n    \"city_ascii\": \"Buenaventura\",\n    \"lat\": 3.8772,\n    \"lng\": -77.0267,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Valle del Cauca\",\n    \"capital\": \"minor\",\n    \"population\": 423927.0,\n    \"id\": 1170287988\n  },\n  {\n    \"city\": \"Pasto\",\n    \"city_ascii\": \"Pasto\",\n    \"lat\": 1.2078,\n    \"lng\": -77.2772,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Nariño\",\n    \"capital\": \"admin\",\n    \"population\": 392930.0,\n    \"id\": 1170320545\n  },\n  {\n    \"city\": \"Pereira\",\n    \"city_ascii\": \"Pereira\",\n    \"lat\": 4.8143,\n    \"lng\": -75.6946,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Risaralda\",\n    \"capital\": \"admin\",\n    \"population\": 590554.0,\n    \"id\": 1170386718\n  },\n  {\n    \"city\": \"Cali\",\n    \"city_ascii\": \"Cali\",\n    \"lat\": 3.4206,\n    \"lng\": -76.5222,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Valle del Cauca\",\n    \"capital\": \"admin\",\n    \"population\": 2471474.0,\n    \"id\": 1170417589\n  },\n  {\n    \"city\": \"Bello\",\n    \"city_ascii\": \"Bello\",\n    \"lat\": 6.3333,\n    \"lng\": -75.5667,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Antioquia\",\n    \"capital\": \"minor\",\n    \"population\": 495483.0,\n    \"id\": 1170423489\n  },\n  {\n    \"city\": \"Villavicencio\",\n    \"city_ascii\": \"Villavicencio\",\n    \"lat\": 4.15,\n    \"lng\": -73.6333,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Meta\",\n    \"capital\": \"admin\",\n    \"population\": 664148.0,\n    \"id\": 1170426927\n  },\n  {\n    \"city\": \"Valledupar\",\n    \"city_ascii\": \"Valledupar\",\n    \"lat\": 10.4833,\n    \"lng\": -73.25,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Cesar\",\n    \"capital\": \"admin\",\n    \"population\": 544134.0,\n    \"id\": 1170481949\n  },\n  {\n    \"city\": \"Bogotá\",\n    \"city_ascii\": \"Bogota\",\n    \"lat\": 4.7111,\n    \"lng\": -74.0722,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Bogotá\",\n    \"capital\": \"primary\",\n    \"population\": 7968095.0,\n    \"id\": 1170483426\n  },\n  {\n    \"city\": \"Soacha\",\n    \"city_ascii\": \"Soacha\",\n    \"lat\": 4.5872,\n    \"lng\": -74.2214,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Cundinamarca\",\n    \"capital\": \"minor\",\n    \"population\": 522442.0,\n    \"id\": 1170512000\n  },\n  {\n    \"city\": \"Palermo\",\n    \"city_ascii\": \"Palermo\",\n    \"lat\": 2.8917,\n    \"lng\": -75.4375,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Huila\",\n    \"capital\": \"minor\",\n    \"population\": 800000.0,\n    \"id\": 1170614290\n  },\n  {\n    \"city\": \"Medellín\",\n    \"city_ascii\": \"Medellin\",\n    \"lat\": 6.2308,\n    \"lng\": -75.5906,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Antioquia\",\n    \"capital\": \"admin\",\n    \"population\": 2529403.0,\n    \"id\": 1170680389\n  },\n  {\n    \"city\": \"Santa Marta\",\n    \"city_ascii\": \"Santa Marta\",\n    \"lat\": 11.2419,\n    \"lng\": -74.2053,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Magdalena\",\n    \"capital\": \"admin\",\n    \"population\": 515556.0,\n    \"id\": 1170715594\n  },\n  {\n    \"city\": \"Cúcuta\",\n    \"city_ascii\": \"Cucuta\",\n    \"lat\": 7.8942,\n    \"lng\": -72.5039,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Norte de Santander\",\n    \"capital\": \"admin\",\n    \"population\": 750000.0,\n    \"id\": 1170743755\n  },\n  {\n    \"city\": \"Soledad\",\n    \"city_ascii\": \"Soledad\",\n    \"lat\": 10.9167,\n    \"lng\": -74.75,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Atlántico\",\n    \"capital\": \"minor\",\n    \"population\": 698852.0,\n    \"id\": 1170765625\n  },\n  {\n    \"city\": \"Timbío\",\n    \"city_ascii\": \"Timbio\",\n    \"lat\": 2.3445,\n    \"lng\": -76.6839,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Cauca\",\n    \"capital\": \"minor\",\n    \"population\": 4444444.0,\n    \"id\": 1170815311\n  },\n  {\n    \"city\": \"Montería\",\n    \"city_ascii\": \"Monteria\",\n    \"lat\": 8.75,\n    \"lng\": -75.8833,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Córdoba\",\n    \"capital\": \"admin\",\n    \"population\": 505334.0,\n    \"id\": 1170855299\n  },\n  {\n    \"city\": \"Cartagena\",\n    \"city_ascii\": \"Cartagena\",\n    \"lat\": 10.4,\n    \"lng\": -75.5,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Bolívar\",\n    \"capital\": \"admin\",\n    \"population\": 1036412.0,\n    \"id\": 1170886102\n  },\n  {\n    \"city\": \"Manizales\",\n    \"city_ascii\": \"Manizales\",\n    \"lat\": 5.1,\n    \"lng\": -75.55,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Caldas\",\n    \"capital\": \"admin\",\n    \"population\": 434403.0,\n    \"id\": 1170930654\n  },\n  {\n    \"city\": \"Bucaramanga\",\n    \"city_ascii\": \"Bucaramanga\",\n    \"lat\": 7.1333,\n    \"lng\": -73.0,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Santander\",\n    \"capital\": \"admin\",\n    \"population\": 870752.0,\n    \"id\": 1170940590\n  },\n  {\n    \"city\": \"Palmira\",\n    \"city_ascii\": \"Palmira\",\n    \"lat\": 3.5833,\n    \"lng\": -76.25,\n    \"country\": \"Colombia\",\n    \"iso2\": \"CO\",\n    \"iso3\": \"COL\",\n    \"admin_name\": \"Valle del Cauca\",\n    \"capital\": \"minor\",\n    \"population\": 349294.0,\n    \"id\": 1170969619\n  },\n  {\n    \"city\": \"Brazzaville\",\n    \"city_ascii\": \"Brazzaville\",\n    \"lat\": -4.2694,\n    \"lng\": 15.2714,\n    \"country\": \"Congo (Brazzaville)\",\n    \"iso2\": \"CG\",\n    \"iso3\": \"COG\",\n    \"admin_name\": \"Brazzaville\",\n    \"capital\": \"primary\",\n    \"population\": 1827000.0,\n    \"id\": 1178340306\n  },\n  {\n    \"city\": \"Pointe-Noire\",\n    \"city_ascii\": \"Pointe-Noire\",\n    \"lat\": -4.8,\n    \"lng\": 11.85,\n    \"country\": \"Congo (Brazzaville)\",\n    \"iso2\": \"CG\",\n    \"iso3\": \"COG\",\n    \"admin_name\": \"Pointe-Noire\",\n    \"capital\": \"admin\",\n    \"population\": 829134.0,\n    \"id\": 1178411563\n  },\n  {\n    \"city\": \"Kinshasa\",\n    \"city_ascii\": \"Kinshasa\",\n    \"lat\": -4.325,\n    \"lng\": 15.3222,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Kinshasa\",\n    \"capital\": \"primary\",\n    \"population\": 12836000.0,\n    \"id\": 1180000363\n  },\n  {\n    \"city\": \"Bunia\",\n    \"city_ascii\": \"Bunia\",\n    \"lat\": 1.5667,\n    \"lng\": 30.25,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Ituri\",\n    \"capital\": \"admin\",\n    \"population\": 900666.0,\n    \"id\": 1180006418\n  },\n  {\n    \"city\": \"Kananga\",\n    \"city_ascii\": \"Kananga\",\n    \"lat\": -5.897,\n    \"lng\": 22.4488,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Kasaï Central\",\n    \"capital\": \"admin\",\n    \"population\": 1971704.0,\n    \"id\": 1180172460\n  },\n  {\n    \"city\": \"Uvira\",\n    \"city_ascii\": \"Uvira\",\n    \"lat\": -3.4,\n    \"lng\": 29.15,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Sud-Kivu\",\n    \"capital\": null,\n    \"population\": 590000.0,\n    \"id\": 1180205443\n  },\n  {\n    \"city\": \"Kolwezi\",\n    \"city_ascii\": \"Kolwezi\",\n    \"lat\": -10.7167,\n    \"lng\": 25.4667,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Lualaba\",\n    \"capital\": \"admin\",\n    \"population\": 572942.0,\n    \"id\": 1180380965\n  },\n  {\n    \"city\": \"Mbuji-Mayi\",\n    \"city_ascii\": \"Mbuji-Mayi\",\n    \"lat\": -6.15,\n    \"lng\": 23.6,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Kasaï Oriental\",\n    \"capital\": \"admin\",\n    \"population\": 2643000.0,\n    \"id\": 1180399586\n  },\n  {\n    \"city\": \"Bukavu\",\n    \"city_ascii\": \"Bukavu\",\n    \"lat\": -2.5,\n    \"lng\": 28.8667,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Sud-Kivu\",\n    \"capital\": \"admin\",\n    \"population\": 1133000.0,\n    \"id\": 1180475821\n  },\n  {\n    \"city\": \"Kisangani\",\n    \"city_ascii\": \"Kisangani\",\n    \"lat\": 0.5153,\n    \"lng\": 25.1911,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Tshopo\",\n    \"capital\": \"admin\",\n    \"population\": 935977.0,\n    \"id\": 1180478201\n  },\n  {\n    \"city\": \"Lubumbashi\",\n    \"city_ascii\": \"Lubumbashi\",\n    \"lat\": -11.6647,\n    \"lng\": 27.4794,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Haut-Katanga\",\n    \"capital\": \"admin\",\n    \"population\": 1786397.0,\n    \"id\": 1180506234\n  },\n  {\n    \"city\": \"Kikwit\",\n    \"city_ascii\": \"Kikwit\",\n    \"lat\": -5.0386,\n    \"lng\": 18.8181,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Kwilu\",\n    \"capital\": null,\n    \"population\": 458000.0,\n    \"id\": 1180518247\n  },\n  {\n    \"city\": \"Tshikapa\",\n    \"city_ascii\": \"Tshikapa\",\n    \"lat\": -6.4167,\n    \"lng\": 20.8,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Kasaï\",\n    \"capital\": null,\n    \"population\": 732000.0,\n    \"id\": 1180581239\n  },\n  {\n    \"city\": \"Mbandaka\",\n    \"city_ascii\": \"Mbandaka\",\n    \"lat\": 0.0478,\n    \"lng\": 18.2558,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Équateur\",\n    \"capital\": \"admin\",\n    \"population\": 1187837.0,\n    \"id\": 1180720887\n  },\n  {\n    \"city\": \"Likasi\",\n    \"city_ascii\": \"Likasi\",\n    \"lat\": -10.9833,\n    \"lng\": 26.7333,\n    \"country\": \"Congo (Kinshasa)\",\n    \"iso2\": \"CD\",\n    \"iso3\": \"COD\",\n    \"admin_name\": \"Haut-Katanga\",\n    \"capital\": null,\n    \"population\": 495000.0,\n    \"id\": 1180978192\n  },\n  {\n    \"city\": \"San José\",\n    \"city_ascii\": \"San Jose\",\n    \"lat\": 9.9325,\n    \"lng\": -84.08,\n    \"country\": \"Costa Rica\",\n    \"iso2\": \"CR\",\n    \"iso3\": \"CRI\",\n    \"admin_name\": \"San José\",\n    \"capital\": \"primary\",\n    \"population\": 1543000.0,\n    \"id\": 1188749877\n  },\n  {\n    \"city\": \"Zagreb\",\n    \"city_ascii\": \"Zagreb\",\n    \"lat\": 45.8167,\n    \"lng\": 15.9833,\n    \"country\": \"Croatia\",\n    \"iso2\": \"HR\",\n    \"iso3\": \"HRV\",\n    \"admin_name\": \"Zagreb, Grad\",\n    \"capital\": \"primary\",\n    \"population\": 809268.0,\n    \"id\": 1191233290\n  },\n  {\n    \"city\": \"Havana\",\n    \"city_ascii\": \"Havana\",\n    \"lat\": 23.1367,\n    \"lng\": -82.3589,\n    \"country\": \"Cuba\",\n    \"iso2\": \"CU\",\n    \"iso3\": \"CUB\",\n    \"admin_name\": \"La Habana\",\n    \"capital\": \"primary\",\n    \"population\": 2141652.0,\n    \"id\": 1192752771\n  },\n  {\n    \"city\": \"Santiago de Cuba\",\n    \"city_ascii\": \"Santiago de Cuba\",\n    \"lat\": 20.0217,\n    \"lng\": -75.8294,\n    \"country\": \"Cuba\",\n    \"iso2\": \"CU\",\n    \"iso3\": \"CUB\",\n    \"admin_name\": \"Santiago de Cuba\",\n    \"capital\": \"admin\",\n    \"population\": 917340.0,\n    \"id\": 1192766111\n  },\n  {\n    \"city\": \"Holguín\",\n    \"city_ascii\": \"Holguin\",\n    \"lat\": 20.8869,\n    \"lng\": -76.2592,\n    \"country\": \"Cuba\",\n    \"iso2\": \"CU\",\n    \"iso3\": \"CUB\",\n    \"admin_name\": \"Holguín\",\n    \"capital\": \"admin\",\n    \"population\": 350191.0,\n    \"id\": 1192920574\n  },\n  {\n    \"city\": \"Olomouc\",\n    \"city_ascii\": \"Olomouc\",\n    \"lat\": 49.5939,\n    \"lng\": 17.2508,\n    \"country\": \"Czechia\",\n    \"iso2\": \"CZ\",\n    \"iso3\": \"CZE\",\n    \"admin_name\": \"Olomoucký Kraj\",\n    \"capital\": \"admin\",\n    \"population\": 384000.0,\n    \"id\": 1203328061\n  },\n  {\n    \"city\": \"Brno\",\n    \"city_ascii\": \"Brno\",\n    \"lat\": 49.1925,\n    \"lng\": 16.6083,\n    \"country\": \"Czechia\",\n    \"iso2\": \"CZ\",\n    \"iso3\": \"CZE\",\n    \"admin_name\": \"Jihomoravský Kraj\",\n    \"capital\": \"admin\",\n    \"population\": 382405.0,\n    \"id\": 1203676514\n  },\n  {\n    \"city\": \"Prague\",\n    \"city_ascii\": \"Prague\",\n    \"lat\": 50.0875,\n    \"lng\": 14.4214,\n    \"country\": \"Czechia\",\n    \"iso2\": \"CZ\",\n    \"iso3\": \"CZE\",\n    \"admin_name\": \"Praha\",\n    \"capital\": \"primary\",\n    \"population\": 1335084.0,\n    \"id\": 1203744823\n  },\n  {\n    \"city\": \"Abomey-Calavi\",\n    \"city_ascii\": \"Abomey-Calavi\",\n    \"lat\": 6.4486,\n    \"lng\": 2.3556,\n    \"country\": \"Benin\",\n    \"iso2\": \"BJ\",\n    \"iso3\": \"BEN\",\n    \"admin_name\": \"Atlantique\",\n    \"capital\": null,\n    \"population\": 655965.0,\n    \"id\": 1204016569\n  },\n  {\n    \"city\": \"Cotonou\",\n    \"city_ascii\": \"Cotonou\",\n    \"lat\": 6.3667,\n    \"lng\": 2.4333,\n    \"country\": \"Benin\",\n    \"iso2\": \"BJ\",\n    \"iso3\": \"BEN\",\n    \"admin_name\": \"Littoral\",\n    \"capital\": \"primary\",\n    \"population\": 762000.0,\n    \"id\": 1204955174\n  },\n  {\n    \"city\": \"Copenhagen\",\n    \"city_ascii\": \"Copenhagen\",\n    \"lat\": 55.6761,\n    \"lng\": 12.5683,\n    \"country\": \"Denmark\",\n    \"iso2\": \"DK\",\n    \"iso3\": \"DNK\",\n    \"admin_name\": \"Hovedstaden\",\n    \"capital\": \"primary\",\n    \"population\": 1366301.0,\n    \"id\": 1208763942\n  },\n  {\n    \"city\": \"Santo Domingo\",\n    \"city_ascii\": \"Santo Domingo\",\n    \"lat\": 18.4764,\n    \"lng\": -69.8933,\n    \"country\": \"Dominican Republic\",\n    \"iso2\": \"DO\",\n    \"iso3\": \"DOM\",\n    \"admin_name\": \"Ozama\",\n    \"capital\": \"primary\",\n    \"population\": 2581827.0,\n    \"id\": 1214636202\n  },\n  {\n    \"city\": \"Santo Domingo Este\",\n    \"city_ascii\": \"Santo Domingo Este\",\n    \"lat\": 18.4855,\n    \"lng\": -69.8734,\n    \"country\": \"Dominican Republic\",\n    \"iso2\": \"DO\",\n    \"iso3\": \"DOM\",\n    \"admin_name\": \"Ozama\",\n    \"capital\": \"admin\",\n    \"population\": 948855.0,\n    \"id\": 1214664832\n  },\n  {\n    \"city\": \"Santiago\",\n    \"city_ascii\": \"Santiago\",\n    \"lat\": 19.4572,\n    \"lng\": -70.6889,\n    \"country\": \"Dominican Republic\",\n    \"iso2\": \"DO\",\n    \"iso3\": \"DOM\",\n    \"admin_name\": \"Cibao Norte\",\n    \"capital\": \"admin\",\n    \"population\": 1343423.0,\n    \"id\": 1214985348\n  },\n  {\n    \"city\": \"Quito\",\n    \"city_ascii\": \"Quito\",\n    \"lat\": -0.22,\n    \"lng\": -78.5125,\n    \"country\": \"Ecuador\",\n    \"iso2\": \"EC\",\n    \"iso3\": \"ECU\",\n    \"admin_name\": \"Pichincha\",\n    \"capital\": \"primary\",\n    \"population\": 2011388.0,\n    \"id\": 1218441993\n  },\n  {\n    \"city\": \"Guayaquil\",\n    \"city_ascii\": \"Guayaquil\",\n    \"lat\": -2.19,\n    \"lng\": -79.8875,\n    \"country\": \"Ecuador\",\n    \"iso2\": \"EC\",\n    \"iso3\": \"ECU\",\n    \"admin_name\": \"Guayas\",\n    \"capital\": \"admin\",\n    \"population\": 2723665.0,\n    \"id\": 1218802178\n  },\n  {\n    \"city\": \"San Salvador\",\n    \"city_ascii\": \"San Salvador\",\n    \"lat\": 13.6989,\n    \"lng\": -89.1914,\n    \"country\": \"El Salvador\",\n    \"iso2\": \"SV\",\n    \"iso3\": \"SLV\",\n    \"admin_name\": \"San Salvador\",\n    \"capital\": \"primary\",\n    \"population\": 567698.0,\n    \"id\": 1222647454\n  },\n  {\n    \"city\": \"Usulután\",\n    \"city_ascii\": \"Usulutan\",\n    \"lat\": 13.35,\n    \"lng\": -88.45,\n    \"country\": \"El Salvador\",\n    \"iso2\": \"SV\",\n    \"iso3\": \"SLV\",\n    \"admin_name\": \"Usulután\",\n    \"capital\": \"admin\",\n    \"population\": 378606.0,\n    \"id\": 1222984157\n  },\n  {\n    \"city\": \"Godē\",\n    \"city_ascii\": \"Gode\",\n    \"lat\": 5.9527,\n    \"lng\": 43.5516,\n    \"country\": \"Ethiopia\",\n    \"iso2\": \"ET\",\n    \"iso3\": \"ETH\",\n    \"admin_name\": \"Sumalē\",\n    \"capital\": null,\n    \"population\": 980782.0,\n    \"id\": 1231128743\n  },\n  {\n    \"city\": \"Ērer Sātā\",\n    \"city_ascii\": \"Erer Sata\",\n    \"lat\": 9.5667,\n    \"lng\": 41.3833,\n    \"country\": \"Ethiopia\",\n    \"iso2\": \"ET\",\n    \"iso3\": \"ETH\",\n    \"admin_name\": \"Sumalē\",\n    \"capital\": null,\n    \"population\": 649000.0,\n    \"id\": 1231563638\n  },\n  {\n    \"city\": \"Addis Ababa\",\n    \"city_ascii\": \"Addis Ababa\",\n    \"lat\": 9.03,\n    \"lng\": 38.74,\n    \"country\": \"Ethiopia\",\n    \"iso2\": \"ET\",\n    \"iso3\": \"ETH\",\n    \"admin_name\": \"Ādīs Ābeba\",\n    \"capital\": \"primary\",\n    \"population\": 3041002.0,\n    \"id\": 1231824991\n  },\n  {\n    \"city\": \"Asmara\",\n    \"city_ascii\": \"Asmara\",\n    \"lat\": 15.3228,\n    \"lng\": 38.925,\n    \"country\": \"Eritrea\",\n    \"iso2\": \"ER\",\n    \"iso3\": \"ERI\",\n    \"admin_name\": \"Ma’ĭkel\",\n    \"capital\": \"primary\",\n    \"population\": 963000.0,\n    \"id\": 1232791236\n  },\n  {\n    \"city\": \"Tallinn\",\n    \"city_ascii\": \"Tallinn\",\n    \"lat\": 59.4372,\n    \"lng\": 24.7453,\n    \"country\": \"Estonia\",\n    \"iso2\": \"EE\",\n    \"iso3\": \"EST\",\n    \"admin_name\": \"Tallinn\",\n    \"capital\": \"primary\",\n    \"population\": 438341.0,\n    \"id\": 1233260021\n  },\n  {\n    \"city\": \"Helsinki\",\n    \"city_ascii\": \"Helsinki\",\n    \"lat\": 60.1708,\n    \"lng\": 24.9375,\n    \"country\": \"Finland\",\n    \"iso2\": \"FI\",\n    \"iso3\": \"FIN\",\n    \"admin_name\": \"Uusimaa\",\n    \"capital\": \"primary\",\n    \"population\": 1268296.0,\n    \"id\": 1246177997\n  },\n  {\n    \"city\": \"Paris\",\n    \"city_ascii\": \"Paris\",\n    \"lat\": 48.8567,\n    \"lng\": 2.3522,\n    \"country\": \"France\",\n    \"iso2\": \"FR\",\n    \"iso3\": \"FRA\",\n    \"admin_name\": \"Île-de-France\",\n    \"capital\": \"primary\",\n    \"population\": 11060000.0,\n    \"id\": 1250015082\n  },\n  {\n    \"city\": \"Lyon\",\n    \"city_ascii\": \"Lyon\",\n    \"lat\": 45.76,\n    \"lng\": 4.84,\n    \"country\": \"France\",\n    \"iso2\": \"FR\",\n    \"iso3\": \"FRA\",\n    \"admin_name\": \"Auvergne-Rhône-Alpes\",\n    \"capital\": \"admin\",\n    \"population\": 522969.0,\n    \"id\": 1250196189\n  },\n  {\n    \"city\": \"Toulouse\",\n    \"city_ascii\": \"Toulouse\",\n    \"lat\": 43.6045,\n    \"lng\": 1.444,\n    \"country\": \"France\",\n    \"iso2\": \"FR\",\n    \"iso3\": \"FRA\",\n    \"admin_name\": \"Occitanie\",\n    \"capital\": \"admin\",\n    \"population\": 493465.0,\n    \"id\": 1250258110\n  },\n  {\n    \"city\": \"Marseille\",\n    \"city_ascii\": \"Marseille\",\n    \"lat\": 43.2964,\n    \"lng\": 5.37,\n    \"country\": \"France\",\n    \"iso2\": \"FR\",\n    \"iso3\": \"FRA\",\n    \"admin_name\": \"Provence-Alpes-Côte d’Azur\",\n    \"capital\": \"admin\",\n    \"population\": 870731.0,\n    \"id\": 1250774071\n  },\n  {\n    \"city\": \"Nice\",\n    \"city_ascii\": \"Nice\",\n    \"lat\": 43.7034,\n    \"lng\": 7.2663,\n    \"country\": \"France\",\n    \"iso2\": \"FR\",\n    \"iso3\": \"FRA\",\n    \"admin_name\": \"Provence-Alpes-Côte d’Azur\",\n    \"capital\": \"minor\",\n    \"population\": 342669.0,\n    \"id\": 1250774553\n  },\n  {\n    \"city\": \"Djibouti\",\n    \"city_ascii\": \"Djibouti\",\n    \"lat\": 11.5883,\n    \"lng\": 43.145,\n    \"country\": \"Djibouti\",\n    \"iso2\": \"DJ\",\n    \"iso3\": \"DJI\",\n    \"admin_name\": \"Djibouti\",\n    \"capital\": \"primary\",\n    \"population\": 603900.0,\n    \"id\": 1262028958\n  },\n  {\n    \"city\": \"Libreville\",\n    \"city_ascii\": \"Libreville\",\n    \"lat\": 0.3903,\n    \"lng\": 9.4542,\n    \"country\": \"Gabon\",\n    \"iso2\": \"GA\",\n    \"iso3\": \"GAB\",\n    \"admin_name\": \"Estuaire\",\n    \"capital\": \"primary\",\n    \"population\": 797003.0,\n    \"id\": 1266952885\n  },\n  {\n    \"city\": \"Tbilisi\",\n    \"city_ascii\": \"Tbilisi\",\n    \"lat\": 41.7225,\n    \"lng\": 44.7925,\n    \"country\": \"Georgia\",\n    \"iso2\": \"GE\",\n    \"iso3\": \"GEO\",\n    \"admin_name\": \"Tbilisi\",\n    \"capital\": \"primary\",\n    \"population\": 1118035.0,\n    \"id\": 1268203191\n  },\n  {\n    \"city\": \"Serekunda\",\n    \"city_ascii\": \"Serekunda\",\n    \"lat\": 13.4333,\n    \"lng\": -16.6667,\n    \"country\": \"The Gambia\",\n    \"iso2\": \"GM\",\n    \"iso3\": \"GMB\",\n    \"admin_name\": \"Kanifing\",\n    \"capital\": null,\n    \"population\": 340000.0,\n    \"id\": 1270640044\n  },\n  {\n    \"city\": \"Banjul\",\n    \"city_ascii\": \"Banjul\",\n    \"lat\": 13.4531,\n    \"lng\": -16.5775,\n    \"country\": \"The Gambia\",\n    \"iso2\": \"GM\",\n    \"iso3\": \"GMB\",\n    \"admin_name\": \"Banjul\",\n    \"capital\": \"primary\",\n    \"population\": 413397.0,\n    \"id\": 1270723713\n  },\n  {\n    \"city\": \"Wuppertal\",\n    \"city_ascii\": \"Wuppertal\",\n    \"lat\": 51.2667,\n    \"lng\": 7.1833,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"North Rhine-Westphalia\",\n    \"capital\": \"minor\",\n    \"population\": 355004.0,\n    \"id\": 1276004611\n  },\n  {\n    \"city\": \"Cologne\",\n    \"city_ascii\": \"Cologne\",\n    \"lat\": 50.9364,\n    \"lng\": 6.9528,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"North Rhine-Westphalia\",\n    \"capital\": null,\n    \"population\": 1083498.0,\n    \"id\": 1276015998\n  },\n  {\n    \"city\": \"Hamburg\",\n    \"city_ascii\": \"Hamburg\",\n    \"lat\": 53.55,\n    \"lng\": 10.0,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"Hamburg\",\n    \"capital\": \"admin\",\n    \"population\": 2484800.0,\n    \"id\": 1276041799\n  },\n  {\n    \"city\": \"Frankfurt\",\n    \"city_ascii\": \"Frankfurt\",\n    \"lat\": 50.1106,\n    \"lng\": 8.6822,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"Hesse\",\n    \"capital\": \"minor\",\n    \"population\": 764104.0,\n    \"id\": 1276054552\n  },\n  {\n    \"city\": \"Nuremberg\",\n    \"city_ascii\": \"Nuremberg\",\n    \"lat\": 49.4539,\n    \"lng\": 11.0775,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"Bavaria\",\n    \"capital\": \"minor\",\n    \"population\": 515543.0,\n    \"id\": 1276166609\n  },\n  {\n    \"city\": \"Stuttgart\",\n    \"city_ascii\": \"Stuttgart\",\n    \"lat\": 48.7775,\n    \"lng\": 9.18,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"Baden-Württemberg\",\n    \"capital\": \"admin\",\n    \"population\": 2787724.0,\n    \"id\": 1276171358\n  },\n  {\n    \"city\": \"Bochum\",\n    \"city_ascii\": \"Bochum\",\n    \"lat\": 51.4819,\n    \"lng\": 7.2158,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"North Rhine-Westphalia\",\n    \"capital\": \"minor\",\n    \"population\": 364454.0,\n    \"id\": 1276227288\n  },\n  {\n    \"city\": \"Bremen\",\n    \"city_ascii\": \"Bremen\",\n    \"lat\": 53.0833,\n    \"lng\": 8.8,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"Bremen\",\n    \"capital\": \"admin\",\n    \"population\": 566573.0,\n    \"id\": 1276376509\n  },\n  {\n    \"city\": \"Berlin\",\n    \"city_ascii\": \"Berlin\",\n    \"lat\": 52.52,\n    \"lng\": 13.405,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"Berlin\",\n    \"capital\": \"primary\",\n    \"population\": 4473101.0,\n    \"id\": 1276451290\n  },\n  {\n    \"city\": \"Hannover\",\n    \"city_ascii\": \"Hannover\",\n    \"lat\": 52.3667,\n    \"lng\": 9.7167,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"Lower Saxony\",\n    \"capital\": \"admin\",\n    \"population\": 542668.0,\n    \"id\": 1276457707\n  },\n  {\n    \"city\": \"Dresden\",\n    \"city_ascii\": \"Dresden\",\n    \"lat\": 51.05,\n    \"lng\": 13.74,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"Saxony\",\n    \"capital\": \"admin\",\n    \"population\": 561922.0,\n    \"id\": 1276561036\n  },\n  {\n    \"city\": \"Dortmund\",\n    \"city_ascii\": \"Dortmund\",\n    \"lat\": 51.5167,\n    \"lng\": 7.4667,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"North Rhine-Westphalia\",\n    \"capital\": \"minor\",\n    \"population\": 587696.0,\n    \"id\": 1276562886\n  },\n  {\n    \"city\": \"Leipzig\",\n    \"city_ascii\": \"Leipzig\",\n    \"lat\": 51.34,\n    \"lng\": 12.375,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"Saxony\",\n    \"capital\": \"minor\",\n    \"population\": 615081.0,\n    \"id\": 1276563678\n  },\n  {\n    \"city\": \"Düsseldorf\",\n    \"city_ascii\": \"Dusseldorf\",\n    \"lat\": 51.2333,\n    \"lng\": 6.7833,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"North Rhine-Westphalia\",\n    \"capital\": \"admin\",\n    \"population\": 645923.0,\n    \"id\": 1276615258\n  },\n  {\n    \"city\": \"Munich\",\n    \"city_ascii\": \"Munich\",\n    \"lat\": 48.1375,\n    \"lng\": 11.575,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"Bavaria\",\n    \"capital\": \"admin\",\n    \"population\": 2606021.0,\n    \"id\": 1276692352\n  },\n  {\n    \"city\": \"Essen\",\n    \"city_ascii\": \"Essen\",\n    \"lat\": 51.4508,\n    \"lng\": 7.0131,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"North Rhine-Westphalia\",\n    \"capital\": \"minor\",\n    \"population\": 582415.0,\n    \"id\": 1276769247\n  },\n  {\n    \"city\": \"Duisburg\",\n    \"city_ascii\": \"Duisburg\",\n    \"lat\": 51.4347,\n    \"lng\": 6.7625,\n    \"country\": \"Germany\",\n    \"iso2\": \"DE\",\n    \"iso3\": \"DEU\",\n    \"admin_name\": \"North Rhine-Westphalia\",\n    \"capital\": \"minor\",\n    \"population\": 495885.0,\n    \"id\": 1276977172\n  },\n  {\n    \"city\": \"Boankra\",\n    \"city_ascii\": \"Boankra\",\n    \"lat\": 6.6944,\n    \"lng\": -1.4028,\n    \"country\": \"Ghana\",\n    \"iso2\": \"GH\",\n    \"iso3\": \"GHA\",\n    \"admin_name\": \"Ashanti\",\n    \"capital\": null,\n    \"population\": 3348000.0,\n    \"id\": 1288164978\n  },\n  {\n    \"city\": \"Kumasi\",\n    \"city_ascii\": \"Kumasi\",\n    \"lat\": 6.6667,\n    \"lng\": -1.6167,\n    \"country\": \"Ghana\",\n    \"iso2\": \"GH\",\n    \"iso3\": \"GHA\",\n    \"admin_name\": \"Ashanti\",\n    \"capital\": \"admin\",\n    \"population\": 2069350.0,\n    \"id\": 1288181103\n  },\n  {\n    \"city\": \"Accra\",\n    \"city_ascii\": \"Accra\",\n    \"lat\": 5.55,\n    \"lng\": -0.2,\n    \"country\": \"Ghana\",\n    \"iso2\": \"GH\",\n    \"iso3\": \"GHA\",\n    \"admin_name\": \"Greater Accra\",\n    \"capital\": \"primary\",\n    \"population\": 2388000.0,\n    \"id\": 1288299415\n  },\n  {\n    \"city\": \"Domaa-Ahenkro\",\n    \"city_ascii\": \"Domaa-Ahenkro\",\n    \"lat\": 7.2833,\n    \"lng\": -2.8833,\n    \"country\": \"Ghana\",\n    \"iso2\": \"GH\",\n    \"iso3\": \"GHA\",\n    \"admin_name\": \"Bono\",\n    \"capital\": null,\n    \"population\": 1000000.0,\n    \"id\": 1288459533\n  },\n  {\n    \"city\": \"Tamale\",\n    \"city_ascii\": \"Tamale\",\n    \"lat\": 9.4075,\n    \"lng\": -0.8533,\n    \"country\": \"Ghana\",\n    \"iso2\": \"GH\",\n    \"iso3\": \"GHA\",\n    \"admin_name\": \"Northern\",\n    \"capital\": \"admin\",\n    \"population\": 1095808.0,\n    \"id\": 1288890688\n  },\n  {\n    \"city\": \"Thessaloníki\",\n    \"city_ascii\": \"Thessaloniki\",\n    \"lat\": 40.6403,\n    \"lng\": 22.9347,\n    \"country\": \"Greece\",\n    \"iso2\": \"GR\",\n    \"iso3\": \"GRC\",\n    \"admin_name\": \"Kentrikí Makedonía\",\n    \"capital\": \"admin\",\n    \"population\": 824676.0,\n    \"id\": 1300397999\n  },\n  {\n    \"city\": \"Piraeus\",\n    \"city_ascii\": \"Piraeus\",\n    \"lat\": 37.943,\n    \"lng\": 23.6469,\n    \"country\": \"Greece\",\n    \"iso2\": \"GR\",\n    \"iso3\": \"GRC\",\n    \"admin_name\": \"Attikí\",\n    \"capital\": \"minor\",\n    \"population\": 448997.0,\n    \"id\": 1300458367\n  },\n  {\n    \"city\": \"Athens\",\n    \"city_ascii\": \"Athens\",\n    \"lat\": 37.9842,\n    \"lng\": 23.7281,\n    \"country\": \"Greece\",\n    \"iso2\": \"GR\",\n    \"iso3\": \"GRC\",\n    \"admin_name\": \"Attikí\",\n    \"capital\": \"primary\",\n    \"population\": 3041131.0,\n    \"id\": 1300715560\n  },\n  {\n    \"city\": \"Guatemala City\",\n    \"city_ascii\": \"Guatemala City\",\n    \"lat\": 14.6099,\n    \"lng\": -90.5252,\n    \"country\": \"Guatemala\",\n    \"iso2\": \"GT\",\n    \"iso3\": \"GTM\",\n    \"admin_name\": \"Guatemala\",\n    \"capital\": \"primary\",\n    \"population\": 2934841.0,\n    \"id\": 1320197916\n  },\n  {\n    \"city\": \"Villa Nueva\",\n    \"city_ascii\": \"Villa Nueva\",\n    \"lat\": 14.5314,\n    \"lng\": -90.5964,\n    \"country\": \"Guatemala\",\n    \"iso2\": \"GT\",\n    \"iso3\": \"GTM\",\n    \"admin_name\": \"Guatemala\",\n    \"capital\": \"minor\",\n    \"population\": 618397.0,\n    \"id\": 1320353009\n  },\n  {\n    \"city\": \"Mixco\",\n    \"city_ascii\": \"Mixco\",\n    \"lat\": 14.6338,\n    \"lng\": -90.6146,\n    \"country\": \"Guatemala\",\n    \"iso2\": \"GT\",\n    \"iso3\": \"GTM\",\n    \"admin_name\": \"Guatemala\",\n    \"capital\": \"minor\",\n    \"population\": 517505.0,\n    \"id\": 1320420152\n  },\n  {\n    \"city\": \"Conakry\",\n    \"city_ascii\": \"Conakry\",\n    \"lat\": 9.5092,\n    \"lng\": -13.7122,\n    \"country\": \"Guinea\",\n    \"iso2\": \"GN\",\n    \"iso3\": \"GIN\",\n    \"admin_name\": \"Conakry\",\n    \"capital\": \"primary\",\n    \"population\": 1667864.0,\n    \"id\": 1324568159\n  },\n  {\n    \"city\": \"Mamou\",\n    \"city_ascii\": \"Mamou\",\n    \"lat\": 10.3833,\n    \"lng\": -12.0833,\n    \"country\": \"Guinea\",\n    \"iso2\": \"GN\",\n    \"iso3\": \"GIN\",\n    \"admin_name\": \"Mamou\",\n    \"capital\": \"admin\",\n    \"population\": 376269.0,\n    \"id\": 1324990909\n  },\n  {\n    \"city\": \"Carrefour\",\n    \"city_ascii\": \"Carrefour\",\n    \"lat\": 18.5344,\n    \"lng\": -72.4094,\n    \"country\": \"Haiti\",\n    \"iso2\": \"HT\",\n    \"iso3\": \"HTI\",\n    \"admin_name\": \"Ouest\",\n    \"capital\": null,\n    \"population\": 511345.0,\n    \"id\": 1332000098\n  },\n  {\n    \"city\": \"Pétion-Ville\",\n    \"city_ascii\": \"Petion-Ville\",\n    \"lat\": 18.5128,\n    \"lng\": -72.2864,\n    \"country\": \"Haiti\",\n    \"iso2\": \"HT\",\n    \"iso3\": \"HTI\",\n    \"admin_name\": \"Ouest\",\n    \"capital\": null,\n    \"population\": 359615.0,\n    \"id\": 1332051873\n  },\n  {\n    \"city\": \"Port-au-Prince\",\n    \"city_ascii\": \"Port-au-Prince\",\n    \"lat\": 18.5333,\n    \"lng\": -72.3333,\n    \"country\": \"Haiti\",\n    \"iso2\": \"HT\",\n    \"iso3\": \"HTI\",\n    \"admin_name\": \"Ouest\",\n    \"capital\": \"primary\",\n    \"population\": 987310.0,\n    \"id\": 1332401940\n  },\n  {\n    \"city\": \"Tegucigalpa\",\n    \"city_ascii\": \"Tegucigalpa\",\n    \"lat\": 14.1,\n    \"lng\": -87.2167,\n    \"country\": \"Honduras\",\n    \"iso2\": \"HN\",\n    \"iso3\": \"HND\",\n    \"admin_name\": \"Francisco Morazán\",\n    \"capital\": \"primary\",\n    \"population\": 1682725.0,\n    \"id\": 1340344059\n  },\n  {\n    \"city\": \"San Pedro Sula\",\n    \"city_ascii\": \"San Pedro Sula\",\n    \"lat\": 15.5,\n    \"lng\": -88.0333,\n    \"country\": \"Honduras\",\n    \"iso2\": \"HN\",\n    \"iso3\": \"HND\",\n    \"admin_name\": \"Cortés\",\n    \"capital\": \"admin\",\n    \"population\": 760182.0,\n    \"id\": 1340568412\n  },\n  {\n    \"city\": \"Comayagüela\",\n    \"city_ascii\": \"Comayaguela\",\n    \"lat\": 14.0981,\n    \"lng\": -87.2097,\n    \"country\": \"Honduras\",\n    \"iso2\": \"HN\",\n    \"iso3\": \"HND\",\n    \"admin_name\": \"Francisco Morazán\",\n    \"capital\": null,\n    \"population\": 1250000.0,\n    \"id\": 1340762485\n  },\n  {\n    \"city\": \"Sham Shui Po\",\n    \"city_ascii\": \"Sham Shui Po\",\n    \"lat\": 22.3307,\n    \"lng\": 114.1622,\n    \"country\": \"Hong Kong\",\n    \"iso2\": \"HK\",\n    \"iso3\": \"HKG\",\n    \"admin_name\": null,\n    \"capital\": null,\n    \"population\": 405869.0,\n    \"id\": 1344000058\n  },\n  {\n    \"city\": \"Kowloon City\",\n    \"city_ascii\": \"Kowloon City\",\n    \"lat\": 22.3282,\n    \"lng\": 114.1916,\n    \"country\": \"Hong Kong\",\n    \"iso2\": \"HK\",\n    \"iso3\": \"HKG\",\n    \"admin_name\": null,\n    \"capital\": null,\n    \"population\": 418732.0,\n    \"id\": 1344000061\n  },\n  {\n    \"city\": \"Kowloon\",\n    \"city_ascii\": \"Kowloon\",\n    \"lat\": 22.3167,\n    \"lng\": 114.1833,\n    \"country\": \"Hong Kong\",\n    \"iso2\": \"HK\",\n    \"iso3\": \"HKG\",\n    \"admin_name\": null,\n    \"capital\": null,\n    \"population\": 2108419.0,\n    \"id\": 1344538284\n  },\n  {\n    \"city\": \"Sha Tin\",\n    \"city_ascii\": \"Sha Tin\",\n    \"lat\": 22.3802,\n    \"lng\": 114.1898,\n    \"country\": \"Hong Kong\",\n    \"iso2\": \"HK\",\n    \"iso3\": \"HKG\",\n    \"admin_name\": null,\n    \"capital\": null,\n    \"population\": 640000.0,\n    \"id\": 1344745541\n  },\n  {\n    \"city\": \"Hong Kong\",\n    \"city_ascii\": \"Hong Kong\",\n    \"lat\": 22.3,\n    \"lng\": 114.2,\n    \"country\": \"Hong Kong\",\n    \"iso2\": \"HK\",\n    \"iso3\": \"HKG\",\n    \"admin_name\": null,\n    \"capital\": \"primary\",\n    \"population\": 7450000.0,\n    \"id\": 1344982653\n  },\n  {\n    \"city\": \"Budapest\",\n    \"city_ascii\": \"Budapest\",\n    \"lat\": 47.4925,\n    \"lng\": 19.0514,\n    \"country\": \"Hungary\",\n    \"iso2\": \"HU\",\n    \"iso3\": \"HUN\",\n    \"admin_name\": \"Budapest\",\n    \"capital\": \"primary\",\n    \"population\": 2997958.0,\n    \"id\": 1348611435\n  },\n  {\n    \"city\": \"Noida\",\n    \"city_ascii\": \"Noida\",\n    \"lat\": 28.57,\n    \"lng\": 77.32,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 637272.0,\n    \"id\": 1356002491\n  },\n  {\n    \"city\": \"Āvadi\",\n    \"city_ascii\": \"Avadi\",\n    \"lat\": 13.1097,\n    \"lng\": 80.0972,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": null,\n    \"population\": 345996.0,\n    \"id\": 1356009111\n  },\n  {\n    \"city\": \"Calicut\",\n    \"city_ascii\": \"Calicut\",\n    \"lat\": 11.25,\n    \"lng\": 75.77,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Kerala\",\n    \"capital\": \"minor\",\n    \"population\": 431560.0,\n    \"id\": 1356010401\n  },\n  {\n    \"city\": \"Farīdābād\",\n    \"city_ascii\": \"Faridabad\",\n    \"lat\": 28.4167,\n    \"lng\": 77.3,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Haryāna\",\n    \"capital\": null,\n    \"population\": 1404653.0,\n    \"id\": 1356013205\n  },\n  {\n    \"city\": \"Rasūlpur\",\n    \"city_ascii\": \"Rasulpur\",\n    \"lat\": 28.57,\n    \"lng\": 77.32,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 637272.0,\n    \"id\": 1356018224\n  },\n  {\n    \"city\": \"Bhayandar\",\n    \"city_ascii\": \"Bhayandar\",\n    \"lat\": 19.29,\n    \"lng\": 72.85,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 809378.0,\n    \"id\": 1356019118\n  },\n  {\n    \"city\": \"Bhātpāra\",\n    \"city_ascii\": \"Bhatpara\",\n    \"lat\": 22.87,\n    \"lng\": 88.41,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"West Bengal\",\n    \"capital\": null,\n    \"population\": 386019.0,\n    \"id\": 1356022456\n  },\n  {\n    \"city\": \"Thiruvananthapuram\",\n    \"city_ascii\": \"Thiruvananthapuram\",\n    \"lat\": 8.4875,\n    \"lng\": 76.9525,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Kerala\",\n    \"capital\": \"admin\",\n    \"population\": 743691.0,\n    \"id\": 1356024354\n  },\n  {\n    \"city\": \"Bīkaner\",\n    \"city_ascii\": \"Bikaner\",\n    \"lat\": 28.0167,\n    \"lng\": 73.3119,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Rājasthān\",\n    \"capital\": null,\n    \"population\": 529007.0,\n    \"id\": 1356026593\n  },\n  {\n    \"city\": \"Tumkūr\",\n    \"city_ascii\": \"Tumkur\",\n    \"lat\": 13.34,\n    \"lng\": 77.1,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Karnātaka\",\n    \"capital\": null,\n    \"population\": 599078.0,\n    \"id\": 1356033724\n  },\n  {\n    \"city\": \"Tinnevelly\",\n    \"city_ascii\": \"Tinnevelly\",\n    \"lat\": 8.7136,\n    \"lng\": 77.7567,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": null,\n    \"population\": 497826.0,\n    \"id\": 1356037155\n  },\n  {\n    \"city\": \"Durgāpur\",\n    \"city_ascii\": \"Durgapur\",\n    \"lat\": 23.55,\n    \"lng\": 87.32,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"West Bengal\",\n    \"capital\": null,\n    \"population\": 581409.0,\n    \"id\": 1356045686\n  },\n  {\n    \"city\": \"Gaya\",\n    \"city_ascii\": \"Gaya\",\n    \"lat\": 24.75,\n    \"lng\": 85.01,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Bihār\",\n    \"capital\": null,\n    \"population\": 474093.0,\n    \"id\": 1356045727\n  },\n  {\n    \"city\": \"Ujjain\",\n    \"city_ascii\": \"Ujjain\",\n    \"lat\": 23.17,\n    \"lng\": 75.79,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Madhya Pradesh\",\n    \"capital\": null,\n    \"population\": 515215.0,\n    \"id\": 1356050735\n  },\n  {\n    \"city\": \"Nāgercoil\",\n    \"city_ascii\": \"Nagercoil\",\n    \"lat\": 8.1833,\n    \"lng\": 77.4119,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": null,\n    \"population\": 622759.0,\n    \"id\": 1356051733\n  },\n  {\n    \"city\": \"Ajmer\",\n    \"city_ascii\": \"Ajmer\",\n    \"lat\": 26.4499,\n    \"lng\": 74.6399,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Rājasthān\",\n    \"capital\": null,\n    \"population\": 551101.0,\n    \"id\": 1356058258\n  },\n  {\n    \"city\": \"Kurnool\",\n    \"city_ascii\": \"Kurnool\",\n    \"lat\": 15.83,\n    \"lng\": 78.05,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Andhra Pradesh\",\n    \"capital\": null,\n    \"population\": 457633.0,\n    \"id\": 1356058372\n  },\n  {\n    \"city\": \"Kolkāta\",\n    \"city_ascii\": \"Kolkata\",\n    \"lat\": 22.5675,\n    \"lng\": 88.37,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"West Bengal\",\n    \"capital\": \"admin\",\n    \"population\": 18502000.0,\n    \"id\": 1356060520\n  },\n  {\n    \"city\": \"Sasarām\",\n    \"city_ascii\": \"Sasaram\",\n    \"lat\": 24.95,\n    \"lng\": 84.03,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Bihār\",\n    \"capital\": null,\n    \"population\": 358283.0,\n    \"id\": 1356061200\n  },\n  {\n    \"city\": \"Mathura\",\n    \"city_ascii\": \"Mathura\",\n    \"lat\": 27.4925,\n    \"lng\": 77.6736,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 441894.0,\n    \"id\": 1356066081\n  },\n  {\n    \"city\": \"Bhilai\",\n    \"city_ascii\": \"Bhilai\",\n    \"lat\": 21.21,\n    \"lng\": 81.38,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Chhattīsgarh\",\n    \"capital\": null,\n    \"population\": 624700.0,\n    \"id\": 1356071083\n  },\n  {\n    \"city\": \"Alīgarh\",\n    \"city_ascii\": \"Aligarh\",\n    \"lat\": 27.88,\n    \"lng\": 78.08,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 1131160.0,\n    \"id\": 1356076391\n  },\n  {\n    \"city\": \"Bhīlwāra\",\n    \"city_ascii\": \"Bhilwara\",\n    \"lat\": 25.35,\n    \"lng\": 74.63,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Rājasthān\",\n    \"capital\": null,\n    \"population\": 509483.0,\n    \"id\": 1356077831\n  },\n  {\n    \"city\": \"Pune\",\n    \"city_ascii\": \"Pune\",\n    \"lat\": 18.5203,\n    \"lng\": 73.8567,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 8231000.0,\n    \"id\": 1356081074\n  },\n  {\n    \"city\": \"Akola\",\n    \"city_ascii\": \"Akola\",\n    \"lat\": 20.7,\n    \"lng\": 77.0,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 425817.0,\n    \"id\": 1356089496\n  },\n  {\n    \"city\": \"Gulbarga\",\n    \"city_ascii\": \"Gulbarga\",\n    \"lat\": 17.329,\n    \"lng\": 76.825,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Karnātaka\",\n    \"capital\": null,\n    \"population\": 533587.0,\n    \"id\": 1356091187\n  },\n  {\n    \"city\": \"Āsansol\",\n    \"city_ascii\": \"Asansol\",\n    \"lat\": 23.68,\n    \"lng\": 86.99,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"West Bengal\",\n    \"capital\": null,\n    \"population\": 563917.0,\n    \"id\": 1356093694\n  },\n  {\n    \"city\": \"Korba\",\n    \"city_ascii\": \"Korba\",\n    \"lat\": 22.35,\n    \"lng\": 82.68,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Chhattīsgarh\",\n    \"capital\": null,\n    \"population\": 365253.0,\n    \"id\": 1356093877\n  },\n  {\n    \"city\": \"Raurkela\",\n    \"city_ascii\": \"Raurkela\",\n    \"lat\": 22.2492,\n    \"lng\": 84.8828,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Odisha\",\n    \"capital\": null,\n    \"population\": 600000.0,\n    \"id\": 1356096816\n  },\n  {\n    \"city\": \"Bhilai\",\n    \"city_ascii\": \"Bhilai\",\n    \"lat\": 21.3667,\n    \"lng\": 81.7167,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Chhattīsgarh\",\n    \"capital\": null,\n    \"population\": 625700.0,\n    \"id\": 1356098574\n  },\n  {\n    \"city\": \"Dāsarhalli\",\n    \"city_ascii\": \"Dasarhalli\",\n    \"lat\": 13.0465,\n    \"lng\": 77.513,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Karnātaka\",\n    \"capital\": null,\n    \"population\": 349720.0,\n    \"id\": 1356103194\n  },\n  {\n    \"city\": \"Dhanbād\",\n    \"city_ascii\": \"Dhanbad\",\n    \"lat\": 23.7998,\n    \"lng\": 86.4305,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Jhārkhand\",\n    \"capital\": null,\n    \"population\": 1162472.0,\n    \"id\": 1356103392\n  },\n  {\n    \"city\": \"Jāmnagar\",\n    \"city_ascii\": \"Jamnagar\",\n    \"lat\": 22.47,\n    \"lng\": 70.07,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Gujarāt\",\n    \"capital\": null,\n    \"population\": 479920.0,\n    \"id\": 1356104995\n  },\n  {\n    \"city\": \"Rānchi\",\n    \"city_ascii\": \"Ranchi\",\n    \"lat\": 23.36,\n    \"lng\": 85.33,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Jhārkhand\",\n    \"capital\": \"admin\",\n    \"population\": 1073440.0,\n    \"id\": 1356110588\n  },\n  {\n    \"city\": \"Kolhāpur\",\n    \"city_ascii\": \"Kolhapur\",\n    \"lat\": 16.6917,\n    \"lng\": 74.2333,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 561489.0,\n    \"id\": 1356110593\n  },\n  {\n    \"city\": \"Jabalpur\",\n    \"city_ascii\": \"Jabalpur\",\n    \"lat\": 23.1667,\n    \"lng\": 79.9333,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Madhya Pradesh\",\n    \"capital\": null,\n    \"population\": 1267564.0,\n    \"id\": 1356115460\n  },\n  {\n    \"city\": \"Pānihāti\",\n    \"city_ascii\": \"Panihati\",\n    \"lat\": 22.69,\n    \"lng\": 88.37,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"West Bengal\",\n    \"capital\": null,\n    \"population\": 377347.0,\n    \"id\": 1356118632\n  },\n  {\n    \"city\": \"Sahāranpur\",\n    \"city_ascii\": \"Saharanpur\",\n    \"lat\": 29.964,\n    \"lng\": 77.546,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 705478.0,\n    \"id\": 1356139858\n  },\n  {\n    \"city\": \"Bhubaneshwar\",\n    \"city_ascii\": \"Bhubaneshwar\",\n    \"lat\": 20.27,\n    \"lng\": 85.84,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Odisha\",\n    \"capital\": \"admin\",\n    \"population\": 837737.0,\n    \"id\": 1356140143\n  },\n  {\n    \"city\": \"Karnāl\",\n    \"city_ascii\": \"Karnal\",\n    \"lat\": 29.686,\n    \"lng\": 76.989,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Haryāna\",\n    \"capital\": null,\n    \"population\": 357334.0,\n    \"id\": 1356145204\n  },\n  {\n    \"city\": \"Vārānasi\",\n    \"city_ascii\": \"Varanasi\",\n    \"lat\": 25.3189,\n    \"lng\": 83.0128,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 1198491.0,\n    \"id\": 1356145782\n  },\n  {\n    \"city\": \"Chāpra\",\n    \"city_ascii\": \"Chapra\",\n    \"lat\": 25.7848,\n    \"lng\": 84.7274,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Bihār\",\n    \"capital\": null,\n    \"population\": 567123.0,\n    \"id\": 1356147120\n  },\n  {\n    \"city\": \"Agartala\",\n    \"city_ascii\": \"Agartala\",\n    \"lat\": 23.8333,\n    \"lng\": 91.2833,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tripura\",\n    \"capital\": \"admin\",\n    \"population\": 522613.0,\n    \"id\": 1356148992\n  },\n  {\n    \"city\": \"Agwār\",\n    \"city_ascii\": \"Agwar\",\n    \"lat\": 27.18,\n    \"lng\": 78.02,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 1585705.0,\n    \"id\": 1356151564\n  },\n  {\n    \"city\": \"Rohtak\",\n    \"city_ascii\": \"Rohtak\",\n    \"lat\": 28.8909,\n    \"lng\": 76.5796,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Haryāna\",\n    \"capital\": null,\n    \"population\": 374292.0,\n    \"id\": 1356162915\n  },\n  {\n    \"city\": \"Sīkar\",\n    \"city_ascii\": \"Sikar\",\n    \"lat\": 27.62,\n    \"lng\": 75.15,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Rājasthān\",\n    \"capital\": null,\n    \"population\": 359293.0,\n    \"id\": 1356163729\n  },\n  {\n    \"city\": \"Bhāngar\",\n    \"city_ascii\": \"Bhangar\",\n    \"lat\": 22.58,\n    \"lng\": 88.42,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"West Bengal\",\n    \"capital\": null,\n    \"population\": 632107.0,\n    \"id\": 1356177796\n  },\n  {\n    \"city\": \"Najafgarh\",\n    \"city_ascii\": \"Najafgarh\",\n    \"lat\": 28.6092,\n    \"lng\": 76.9798,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Delhi\",\n    \"capital\": null,\n    \"population\": 1203180.0,\n    \"id\": 1356180206\n  },\n  {\n    \"city\": \"Āgra\",\n    \"city_ascii\": \"Agra\",\n    \"lat\": 27.18,\n    \"lng\": 78.02,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 1585704.0,\n    \"id\": 1356187395\n  },\n  {\n    \"city\": \"Gorakhpur\",\n    \"city_ascii\": \"Gorakhpur\",\n    \"lat\": 26.7637,\n    \"lng\": 83.4039,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 673446.0,\n    \"id\": 1356190221\n  },\n  {\n    \"city\": \"Bellary\",\n    \"city_ascii\": \"Bellary\",\n    \"lat\": 15.1,\n    \"lng\": 76.9167,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Karnātaka\",\n    \"capital\": null,\n    \"population\": 410445.0,\n    \"id\": 1356209152\n  },\n  {\n    \"city\": \"Dhūlia\",\n    \"city_ascii\": \"Dhulia\",\n    \"lat\": 20.8997,\n    \"lng\": 74.7697,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 750000.0,\n    \"id\": 1356224695\n  },\n  {\n    \"city\": \"Mumbai\",\n    \"city_ascii\": \"Mumbai\",\n    \"lat\": 19.0761,\n    \"lng\": 72.8775,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": \"admin\",\n    \"population\": 24973000.0,\n    \"id\": 1356226629\n  },\n  {\n    \"city\": \"Madurai\",\n    \"city_ascii\": \"Madurai\",\n    \"lat\": 9.9252,\n    \"lng\": 78.1198,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": \"minor\",\n    \"population\": 1561129.0,\n    \"id\": 1356257289\n  },\n  {\n    \"city\": \"Kālkāji Devi\",\n    \"city_ascii\": \"Kalkaji Devi\",\n    \"lat\": 28.5485,\n    \"lng\": 77.2513,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Delhi\",\n    \"capital\": null,\n    \"population\": 824177.0,\n    \"id\": 1356264482\n  },\n  {\n    \"city\": \"Udaipur\",\n    \"city_ascii\": \"Udaipur\",\n    \"lat\": 24.58,\n    \"lng\": 73.68,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Rājasthān\",\n    \"capital\": null,\n    \"population\": 451100.0,\n    \"id\": 1356266094\n  },\n  {\n    \"city\": \"Morādābād\",\n    \"city_ascii\": \"Moradabad\",\n    \"lat\": 28.8389,\n    \"lng\": 78.7769,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 887871.0,\n    \"id\": 1356269375\n  },\n  {\n    \"city\": \"Nellore\",\n    \"city_ascii\": \"Nellore\",\n    \"lat\": 14.45,\n    \"lng\": 79.99,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Andhra Pradesh\",\n    \"capital\": null,\n    \"population\": 547621.0,\n    \"id\": 1356280972\n  },\n  {\n    \"city\": \"Jaipur\",\n    \"city_ascii\": \"Jaipur\",\n    \"lat\": 26.9,\n    \"lng\": 75.8,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Rājasthān\",\n    \"capital\": \"admin\",\n    \"population\": 3073350.0,\n    \"id\": 1356293537\n  },\n  {\n    \"city\": \"Quilon\",\n    \"city_ascii\": \"Quilon\",\n    \"lat\": 8.88,\n    \"lng\": 76.6,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Kerala\",\n    \"capital\": null,\n    \"population\": 397419.0,\n    \"id\": 1356304110\n  },\n  {\n    \"city\": \"Ahmedabad\",\n    \"city_ascii\": \"Ahmedabad\",\n    \"lat\": 23.03,\n    \"lng\": 72.58,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Gujarāt\",\n    \"capital\": \"minor\",\n    \"population\": 8009000.0,\n    \"id\": 1356304381\n  },\n  {\n    \"city\": \"Solāpur\",\n    \"city_ascii\": \"Solapur\",\n    \"lat\": 17.68,\n    \"lng\": 75.92,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 951558.0,\n    \"id\": 1356314385\n  },\n  {\n    \"city\": \"Rājkot\",\n    \"city_ascii\": \"Rajkot\",\n    \"lat\": 22.3,\n    \"lng\": 70.7833,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Gujarāt\",\n    \"capital\": null,\n    \"population\": 1335397.0,\n    \"id\": 1356317190\n  },\n  {\n    \"city\": \"Cuddapah\",\n    \"city_ascii\": \"Cuddapah\",\n    \"lat\": 14.47,\n    \"lng\": 78.82,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Andhra Pradesh\",\n    \"capital\": null,\n    \"population\": 344893.0,\n    \"id\": 1356360140\n  },\n  {\n    \"city\": \"Gwalior\",\n    \"city_ascii\": \"Gwalior\",\n    \"lat\": 26.2215,\n    \"lng\": 78.178,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Madhya Pradesh\",\n    \"capital\": null,\n    \"population\": 1069276.0,\n    \"id\": 1356363967\n  },\n  {\n    \"city\": \"Nāgpur\",\n    \"city_ascii\": \"Nagpur\",\n    \"lat\": 21.1497,\n    \"lng\": 79.0806,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": \"admin\",\n    \"population\": 2405665.0,\n    \"id\": 1356365743\n  },\n  {\n    \"city\": \"Guntūr\",\n    \"city_ascii\": \"Guntur\",\n    \"lat\": 16.3008,\n    \"lng\": 80.4428,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Andhra Pradesh\",\n    \"capital\": null,\n    \"population\": 647508.0,\n    \"id\": 1356374905\n  },\n  {\n    \"city\": \"Chennai\",\n    \"city_ascii\": \"Chennai\",\n    \"lat\": 13.0825,\n    \"lng\": 80.275,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": \"admin\",\n    \"population\": 12395000.0,\n    \"id\": 1356374944\n  },\n  {\n    \"city\": \"Raipur\",\n    \"city_ascii\": \"Raipur\",\n    \"lat\": 21.25,\n    \"lng\": 81.63,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Chhattīsgarh\",\n    \"capital\": \"admin\",\n    \"population\": 1010087.0,\n    \"id\": 1356374983\n  },\n  {\n    \"city\": \"Ulhāsnagar\",\n    \"city_ascii\": \"Ulhasnagar\",\n    \"lat\": 19.22,\n    \"lng\": 73.15,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 506098.0,\n    \"id\": 1356375341\n  },\n  {\n    \"city\": \"Meerut\",\n    \"city_ascii\": \"Meerut\",\n    \"lat\": 28.98,\n    \"lng\": 77.71,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 1305429.0,\n    \"id\": 1356390476\n  },\n  {\n    \"city\": \"Belgaum\",\n    \"city_ascii\": \"Belgaum\",\n    \"lat\": 15.85,\n    \"lng\": 74.5,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Karnātaka\",\n    \"capital\": null,\n    \"population\": 488157.0,\n    \"id\": 1356390535\n  },\n  {\n    \"city\": \"Indore\",\n    \"city_ascii\": \"Indore\",\n    \"lat\": 22.7167,\n    \"lng\": 75.8472,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Madhya Pradesh\",\n    \"capital\": null,\n    \"population\": 1994397.0,\n    \"id\": 1356402812\n  },\n  {\n    \"city\": \"Bangalore\",\n    \"city_ascii\": \"Bangalore\",\n    \"lat\": 12.9789,\n    \"lng\": 77.5917,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Karnātaka\",\n    \"capital\": \"admin\",\n    \"population\": 15386000.0,\n    \"id\": 1356410365\n  },\n  {\n    \"city\": \"Shāhjānpur\",\n    \"city_ascii\": \"Shahjanpur\",\n    \"lat\": 27.88,\n    \"lng\": 79.91,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 346103.0,\n    \"id\": 1356415439\n  },\n  {\n    \"city\": \"Mirzāpur\",\n    \"city_ascii\": \"Mirzapur\",\n    \"lat\": 25.146,\n    \"lng\": 82.569,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 2496970.0,\n    \"id\": 1356427908\n  },\n  {\n    \"city\": \"Srīnagar\",\n    \"city_ascii\": \"Srinagar\",\n    \"lat\": 34.09,\n    \"lng\": 74.79,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Jammu and Kashmīr\",\n    \"capital\": \"admin\",\n    \"population\": 1180570.0,\n    \"id\": 1356442950\n  },\n  {\n    \"city\": \"Davangere\",\n    \"city_ascii\": \"Davangere\",\n    \"lat\": 14.4666,\n    \"lng\": 75.9242,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Karnātaka\",\n    \"capital\": null,\n    \"population\": 435125.0,\n    \"id\": 1356445061\n  },\n  {\n    \"city\": \"Patiāla\",\n    \"city_ascii\": \"Patiala\",\n    \"lat\": 30.34,\n    \"lng\": 76.38,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": null,\n    \"population\": 763280.0,\n    \"id\": 1356458416\n  },\n  {\n    \"city\": \"Amrāvati\",\n    \"city_ascii\": \"Amravati\",\n    \"lat\": 20.9258,\n    \"lng\": 77.7647,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 549370.0,\n    \"id\": 1356462099\n  },\n  {\n    \"city\": \"Chinchvad\",\n    \"city_ascii\": \"Chinchvad\",\n    \"lat\": 18.6186,\n    \"lng\": 73.8037,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 1729320.0,\n    \"id\": 1356475483\n  },\n  {\n    \"city\": \"Purnea\",\n    \"city_ascii\": \"Purnea\",\n    \"lat\": 25.778,\n    \"lng\": 87.476,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Bihār\",\n    \"capital\": null,\n    \"population\": 496830.0,\n    \"id\": 1356486511\n  },\n  {\n    \"city\": \"Jammu\",\n    \"city_ascii\": \"Jammu\",\n    \"lat\": 32.73,\n    \"lng\": 74.87,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Jammu and Kashmīr\",\n    \"capital\": \"admin\",\n    \"population\": 502197.0,\n    \"id\": 1356491738\n  },\n  {\n    \"city\": \"Jalandhar\",\n    \"city_ascii\": \"Jalandhar\",\n    \"lat\": 31.2569,\n    \"lng\": 75.4432,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": null,\n    \"population\": 873725.0,\n    \"id\": 1356494816\n  },\n  {\n    \"city\": \"Jamshedpur\",\n    \"city_ascii\": \"Jamshedpur\",\n    \"lat\": 22.7925,\n    \"lng\": 86.1842,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Jhārkhand\",\n    \"capital\": null,\n    \"population\": 1558000.0,\n    \"id\": 1356501259\n  },\n  {\n    \"city\": \"Shorāpur\",\n    \"city_ascii\": \"Shorapur\",\n    \"lat\": 16.52,\n    \"lng\": 76.76,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Karnātaka\",\n    \"capital\": null,\n    \"population\": 412291.0,\n    \"id\": 1356512373\n  },\n  {\n    \"city\": \"Delhi Cantonment\",\n    \"city_ascii\": \"Delhi Cantonment\",\n    \"lat\": 28.6,\n    \"lng\": 77.1333,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Delhi\",\n    \"capital\": null,\n    \"population\": 405633.0,\n    \"id\": 1356526853\n  },\n  {\n    \"city\": \"Loni\",\n    \"city_ascii\": \"Loni\",\n    \"lat\": 28.75,\n    \"lng\": 77.28,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 516082.0,\n    \"id\": 1356528413\n  },\n  {\n    \"city\": \"Kalamboli\",\n    \"city_ascii\": \"Kalamboli\",\n    \"lat\": 19.2333,\n    \"lng\": 73.1333,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 1246381.0,\n    \"id\": 1356537020\n  },\n  {\n    \"city\": \"Tiruppūr\",\n    \"city_ascii\": \"Tiruppur\",\n    \"lat\": 11.1085,\n    \"lng\": 77.3411,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": null,\n    \"population\": 877778.0,\n    \"id\": 1356539761\n  },\n  {\n    \"city\": \"Narela\",\n    \"city_ascii\": \"Narela\",\n    \"lat\": 28.8527,\n    \"lng\": 77.0929,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Delhi\",\n    \"capital\": null,\n    \"population\": 661994.0,\n    \"id\": 1356542019\n  },\n  {\n    \"city\": \"Kūkatpalli\",\n    \"city_ascii\": \"Kukatpalli\",\n    \"lat\": 17.4849,\n    \"lng\": 78.4138,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Andhra Pradesh\",\n    \"capital\": null,\n    \"population\": 385821.0,\n    \"id\": 1356553747\n  },\n  {\n    \"city\": \"Nāsik\",\n    \"city_ascii\": \"Nasik\",\n    \"lat\": 20.0,\n    \"lng\": 73.78,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 1486053.0,\n    \"id\": 1356562598\n  },\n  {\n    \"city\": \"Salem\",\n    \"city_ascii\": \"Salem\",\n    \"lat\": 11.65,\n    \"lng\": 78.15,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": null,\n    \"population\": 693236.0,\n    \"id\": 1356567087\n  },\n  {\n    \"city\": \"Brahmapur\",\n    \"city_ascii\": \"Brahmapur\",\n    \"lat\": 19.315,\n    \"lng\": 84.7941,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Odisha\",\n    \"capital\": null,\n    \"population\": 634220.0,\n    \"id\": 1356569354\n  },\n  {\n    \"city\": \"Alwar\",\n    \"city_ascii\": \"Alwar\",\n    \"lat\": 27.5498,\n    \"lng\": 76.6355,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Rājasthān\",\n    \"capital\": null,\n    \"population\": 341422.0,\n    \"id\": 1356570855\n  },\n  {\n    \"city\": \"Kākināda\",\n    \"city_ascii\": \"Kakinada\",\n    \"lat\": 16.9661,\n    \"lng\": 82.255,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Andhra Pradesh\",\n    \"capital\": null,\n    \"population\": 384182.0,\n    \"id\": 1356573609\n  },\n  {\n    \"city\": \"Cawnpore\",\n    \"city_ascii\": \"Cawnpore\",\n    \"lat\": 26.4499,\n    \"lng\": 80.3319,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 2701324.0,\n    \"id\": 1356575238\n  },\n  {\n    \"city\": \"Bettiah\",\n    \"city_ascii\": \"Bettiah\",\n    \"lat\": 26.8014,\n    \"lng\": 84.5028,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Bihār\",\n    \"capital\": null,\n    \"population\": 414453.0,\n    \"id\": 1356590604\n  },\n  {\n    \"city\": \"Chānda\",\n    \"city_ascii\": \"Chanda\",\n    \"lat\": 19.95,\n    \"lng\": 79.297,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 355739.0,\n    \"id\": 1356592607\n  },\n  {\n    \"city\": \"Guwāhāti\",\n    \"city_ascii\": \"Guwahati\",\n    \"lat\": 26.1722,\n    \"lng\": 91.7458,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Assam\",\n    \"capital\": null,\n    \"population\": 1116267.0,\n    \"id\": 1356593800\n  },\n  {\n    \"city\": \"Padiāla\",\n    \"city_ascii\": \"Padiala\",\n    \"lat\": 30.5667,\n    \"lng\": 76.6333,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": null,\n    \"population\": 406192.0,\n    \"id\": 1356667176\n  },\n  {\n    \"city\": \"Thāne\",\n    \"city_ascii\": \"Thane\",\n    \"lat\": 19.1972,\n    \"lng\": 72.9722,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 1886941.0,\n    \"id\": 1356681152\n  },\n  {\n    \"city\": \"Ambattūr\",\n    \"city_ascii\": \"Ambattur\",\n    \"lat\": 13.1143,\n    \"lng\": 80.1548,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": null,\n    \"population\": 466205.0,\n    \"id\": 1356685959\n  },\n  {\n    \"city\": \"Ghāziābād\",\n    \"city_ascii\": \"Ghaziabad\",\n    \"lat\": 28.67,\n    \"lng\": 77.42,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 2375820.0,\n    \"id\": 1356691871\n  },\n  {\n    \"city\": \"Vishākhapatnam\",\n    \"city_ascii\": \"Vishakhapatnam\",\n    \"lat\": 17.7042,\n    \"lng\": 83.2978,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Andhra Pradesh\",\n    \"capital\": null,\n    \"population\": 2035922.0,\n    \"id\": 1356692563\n  },\n  {\n    \"city\": \"Bareilly\",\n    \"city_ascii\": \"Bareilly\",\n    \"lat\": 28.364,\n    \"lng\": 79.415,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 1000000.0,\n    \"id\": 1356698199\n  },\n  {\n    \"city\": \"Vadodara\",\n    \"city_ascii\": \"Vadodara\",\n    \"lat\": 22.3,\n    \"lng\": 73.2,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Gujarāt\",\n    \"capital\": null,\n    \"population\": 2065771.0,\n    \"id\": 1356705249\n  },\n  {\n    \"city\": \"Vasai\",\n    \"city_ascii\": \"Vasai\",\n    \"lat\": 19.47,\n    \"lng\": 72.8,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 1222390.0,\n    \"id\": 1356707797\n  },\n  {\n    \"city\": \"Kochi\",\n    \"city_ascii\": \"Kochi\",\n    \"lat\": 9.97,\n    \"lng\": 76.28,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Kerala\",\n    \"capital\": null,\n    \"population\": 677381.0,\n    \"id\": 1356707865\n  },\n  {\n    \"city\": \"Jhānsi\",\n    \"city_ascii\": \"Jhansi\",\n    \"lat\": 25.4486,\n    \"lng\": 78.5696,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 507000.0,\n    \"id\": 1356712664\n  },\n  {\n    \"city\": \"Prayagraj\",\n    \"city_ascii\": \"Prayagraj\",\n    \"lat\": 25.4358,\n    \"lng\": 81.8464,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": null,\n    \"population\": 5954391.0,\n    \"id\": 1356718332\n  },\n  {\n    \"city\": \"Salt Lake City\",\n    \"city_ascii\": \"Salt Lake City\",\n    \"lat\": 22.61,\n    \"lng\": 88.4,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"West Bengal\",\n    \"capital\": null,\n    \"population\": 403316.0,\n    \"id\": 1356720205\n  },\n  {\n    \"city\": \"Nānded\",\n    \"city_ascii\": \"Nanded\",\n    \"lat\": 19.15,\n    \"lng\": 77.3,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 550439.0,\n    \"id\": 1356722310\n  },\n  {\n    \"city\": \"Shiliguri\",\n    \"city_ascii\": \"Shiliguri\",\n    \"lat\": 26.71,\n    \"lng\": 88.43,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"West Bengal\",\n    \"capital\": null,\n    \"population\": 701489.0,\n    \"id\": 1356724691\n  },\n  {\n    \"city\": \"Jodhpur\",\n    \"city_ascii\": \"Jodhpur\",\n    \"lat\": 26.28,\n    \"lng\": 73.02,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Rājasthān\",\n    \"capital\": null,\n    \"population\": 1033918.0,\n    \"id\": 1356727084\n  },\n  {\n    \"city\": \"Bhopāl\",\n    \"city_ascii\": \"Bhopal\",\n    \"lat\": 23.25,\n    \"lng\": 77.4167,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Madhya Pradesh\",\n    \"capital\": \"admin\",\n    \"population\": 1798218.0,\n    \"id\": 1356734039\n  },\n  {\n    \"city\": \"Jalgaon\",\n    \"city_ascii\": \"Jalgaon\",\n    \"lat\": 21.004,\n    \"lng\": 75.568,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 460468.0,\n    \"id\": 1356734842\n  },\n  {\n    \"city\": \"Chandīgarh\",\n    \"city_ascii\": \"Chandigarh\",\n    \"lat\": 30.75,\n    \"lng\": 76.78,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Chandīgarh\",\n    \"capital\": \"admin\",\n    \"population\": 1055450.0,\n    \"id\": 1356739179\n  },\n  {\n    \"city\": \"Sūrat\",\n    \"city_ascii\": \"Surat\",\n    \"lat\": 21.1702,\n    \"lng\": 72.8311,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Gujarāt\",\n    \"capital\": null,\n    \"population\": 6538000.0,\n    \"id\": 1356758738\n  },\n  {\n    \"city\": \"Bhāgalpur\",\n    \"city_ascii\": \"Bhagalpur\",\n    \"lat\": 25.25,\n    \"lng\": 87.0,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Bihār\",\n    \"capital\": null,\n    \"population\": 410210.0,\n    \"id\": 1356760990\n  },\n  {\n    \"city\": \"Bhiwandi\",\n    \"city_ascii\": \"Bhiwandi\",\n    \"lat\": 19.2967,\n    \"lng\": 73.0631,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 709665.0,\n    \"id\": 1356763571\n  },\n  {\n    \"city\": \"Vijayavāda\",\n    \"city_ascii\": \"Vijayawada\",\n    \"lat\": 16.5193,\n    \"lng\": 80.6305,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Andhra Pradesh\",\n    \"capital\": null,\n    \"population\": 1048240.0,\n    \"id\": 1356807575\n  },\n  {\n    \"city\": \"Kota\",\n    \"city_ascii\": \"Kota\",\n    \"lat\": 25.18,\n    \"lng\": 75.83,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Rājasthān\",\n    \"capital\": null,\n    \"population\": 1001694.0,\n    \"id\": 1356820310\n  },\n  {\n    \"city\": \"Bilāspur\",\n    \"city_ascii\": \"Bilaspur\",\n    \"lat\": 22.09,\n    \"lng\": 82.15,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Chhattīsgarh\",\n    \"capital\": null,\n    \"population\": 1625502.0,\n    \"id\": 1356820491\n  },\n  {\n    \"city\": \"Patna\",\n    \"city_ascii\": \"Patna\",\n    \"lat\": 25.6,\n    \"lng\": 85.1,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Bihār\",\n    \"capital\": \"admin\",\n    \"population\": 1684222.0,\n    \"id\": 1356821429\n  },\n  {\n    \"city\": \"Hosūr\",\n    \"city_ascii\": \"Hosur\",\n    \"lat\": 12.7409,\n    \"lng\": 77.8253,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": null,\n    \"population\": 345000.0,\n    \"id\": 1356829362\n  },\n  {\n    \"city\": \"Rājahmundry\",\n    \"city_ascii\": \"Rajahmundry\",\n    \"lat\": 16.98,\n    \"lng\": 81.78,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Andhra Pradesh\",\n    \"capital\": null,\n    \"population\": 341831.0,\n    \"id\": 1356831716\n  },\n  {\n    \"city\": \"Gurgaon\",\n    \"city_ascii\": \"Gurgaon\",\n    \"lat\": 28.456,\n    \"lng\": 77.029,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Haryāna\",\n    \"capital\": null,\n    \"population\": 876824.0,\n    \"id\": 1356836043\n  },\n  {\n    \"city\": \"Karūr\",\n    \"city_ascii\": \"Karur\",\n    \"lat\": 10.9601,\n    \"lng\": 78.0766,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": null,\n    \"population\": 358468.0,\n    \"id\": 1356837900\n  },\n  {\n    \"city\": \"Aurangābād\",\n    \"city_ascii\": \"Aurangabad\",\n    \"lat\": 19.88,\n    \"lng\": 75.32,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 1371330.0,\n    \"id\": 1356840670\n  },\n  {\n    \"city\": \"Māndvi\",\n    \"city_ascii\": \"Mandvi\",\n    \"lat\": 19.3,\n    \"lng\": 72.85,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 814655.0,\n    \"id\": 1356843310\n  },\n  {\n    \"city\": \"Darbhanga\",\n    \"city_ascii\": \"Darbhanga\",\n    \"lat\": 26.17,\n    \"lng\": 85.9,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Bihār\",\n    \"capital\": null,\n    \"population\": 380125.0,\n    \"id\": 1356846195\n  },\n  {\n    \"city\": \"Māler Kotla\",\n    \"city_ascii\": \"Maler Kotla\",\n    \"lat\": 30.5167,\n    \"lng\": 75.8833,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": null,\n    \"population\": 374000.0,\n    \"id\": 1356847218\n  },\n  {\n    \"city\": \"Warangal\",\n    \"city_ascii\": \"Warangal\",\n    \"lat\": 17.9689,\n    \"lng\": 79.5941,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Andhra Pradesh\",\n    \"capital\": null,\n    \"population\": 704570.0,\n    \"id\": 1356851618\n  },\n  {\n    \"city\": \"Hyderābād\",\n    \"city_ascii\": \"Hyderabad\",\n    \"lat\": 17.385,\n    \"lng\": 78.4867,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Telangāna\",\n    \"capital\": \"admin\",\n    \"population\": 10494000.0,\n    \"id\": 1356871768\n  },\n  {\n    \"city\": \"Cuttack\",\n    \"city_ascii\": \"Cuttack\",\n    \"lat\": 20.5236,\n    \"lng\": 85.7881,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Odisha\",\n    \"capital\": null,\n    \"population\": 606007.0,\n    \"id\": 1356872061\n  },\n  {\n    \"city\": \"Delhi\",\n    \"city_ascii\": \"Delhi\",\n    \"lat\": 28.61,\n    \"lng\": 77.23,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Delhi\",\n    \"capital\": \"admin\",\n    \"population\": 32226000.0,\n    \"id\": 1356872604\n  },\n  {\n    \"city\": \"Trichinopoly\",\n    \"city_ascii\": \"Trichinopoly\",\n    \"lat\": 10.7903,\n    \"lng\": 78.7047,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": null,\n    \"population\": 916857.0,\n    \"id\": 1356884472\n  },\n  {\n    \"city\": \"Lucknow\",\n    \"city_ascii\": \"Lucknow\",\n    \"lat\": 26.85,\n    \"lng\": 80.95,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttar Pradesh\",\n    \"capital\": \"admin\",\n    \"population\": 3382000.0,\n    \"id\": 1356891790\n  },\n  {\n    \"city\": \"Sāngli\",\n    \"city_ascii\": \"Sangli\",\n    \"lat\": 16.8667,\n    \"lng\": 74.5667,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 436639.0,\n    \"id\": 1356921375\n  },\n  {\n    \"city\": \"Amritsar\",\n    \"city_ascii\": \"Amritsar\",\n    \"lat\": 31.64,\n    \"lng\": 74.86,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": null,\n    \"population\": 1132383.0,\n    \"id\": 1356926507\n  },\n  {\n    \"city\": \"Sirūr\",\n    \"city_ascii\": \"Sirur\",\n    \"lat\": 18.83,\n    \"lng\": 74.38,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 385414.0,\n    \"id\": 1356926718\n  },\n  {\n    \"city\": \"Ludhiāna\",\n    \"city_ascii\": \"Ludhiana\",\n    \"lat\": 30.91,\n    \"lng\": 75.85,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": null,\n    \"population\": 1618879.0,\n    \"id\": 1356929498\n  },\n  {\n    \"city\": \"Sardārshahr\",\n    \"city_ascii\": \"Sardarshahr\",\n    \"lat\": 28.4401,\n    \"lng\": 74.4908,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Rājasthān\",\n    \"capital\": null,\n    \"population\": 382474.0,\n    \"id\": 1356932502\n  },\n  {\n    \"city\": \"Hazāribāgh\",\n    \"city_ascii\": \"Hazaribagh\",\n    \"lat\": 23.98,\n    \"lng\": 85.35,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Jhārkhand\",\n    \"capital\": null,\n    \"population\": 394532.0,\n    \"id\": 1356960055\n  },\n  {\n    \"city\": \"Dehra Dūn\",\n    \"city_ascii\": \"Dehra Dun\",\n    \"lat\": 30.345,\n    \"lng\": 78.029,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Uttarākhand\",\n    \"capital\": \"admin\",\n    \"population\": 578420.0,\n    \"id\": 1356970407\n  },\n  {\n    \"city\": \"Mangalore\",\n    \"city_ascii\": \"Mangalore\",\n    \"lat\": 12.902,\n    \"lng\": 74.8253,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Karnātaka\",\n    \"capital\": null,\n    \"population\": 623841.0,\n    \"id\": 1356972351\n  },\n  {\n    \"city\": \"Ahmadnagar\",\n    \"city_ascii\": \"Ahmadnagar\",\n    \"lat\": 19.08,\n    \"lng\": 74.73,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Mahārāshtra\",\n    \"capital\": null,\n    \"population\": 350859.0,\n    \"id\": 1356972679\n  },\n  {\n    \"city\": \"Vellore\",\n    \"city_ascii\": \"Vellore\",\n    \"lat\": 12.9165,\n    \"lng\": 79.1325,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": null,\n    \"population\": 696110.0,\n    \"id\": 1356977661\n  },\n  {\n    \"city\": \"Bhāvnagar\",\n    \"city_ascii\": \"Bhavnagar\",\n    \"lat\": 21.76,\n    \"lng\": 72.15,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Gujarāt\",\n    \"capital\": null,\n    \"population\": 643365.0,\n    \"id\": 1356982375\n  },\n  {\n    \"city\": \"Hāora\",\n    \"city_ascii\": \"Haora\",\n    \"lat\": 22.58,\n    \"lng\": 88.3294,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"West Bengal\",\n    \"capital\": null,\n    \"population\": 1077075.0,\n    \"id\": 1356986516\n  },\n  {\n    \"city\": \"Coimbatore\",\n    \"city_ascii\": \"Coimbatore\",\n    \"lat\": 11.0168,\n    \"lng\": 76.9558,\n    \"country\": \"India\",\n    \"iso2\": \"IN\",\n    \"iso3\": \"IND\",\n    \"admin_name\": \"Tamil Nādu\",\n    \"capital\": null,\n    \"population\": 959823.0,\n    \"id\": 1356999503\n  },\n  {\n    \"city\": \"Tangerang\",\n    \"city_ascii\": \"Tangerang\",\n    \"lat\": -6.1783,\n    \"lng\": 106.6319,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Barat\",\n    \"capital\": null,\n    \"population\": 2237006.0,\n    \"id\": 1360002844\n  },\n  {\n    \"city\": \"Bekasi\",\n    \"city_ascii\": \"Bekasi\",\n    \"lat\": -6.2349,\n    \"lng\": 106.9923,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Barat\",\n    \"capital\": null,\n    \"population\": 2381053.0,\n    \"id\": 1360006015\n  },\n  {\n    \"city\": \"Lembok\",\n    \"city_ascii\": \"Lembok\",\n    \"lat\": -8.565,\n    \"lng\": 116.351,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Nusa Tenggara Barat\",\n    \"capital\": null,\n    \"population\": 495651.0,\n    \"id\": 1360013261\n  },\n  {\n    \"city\": \"Mataram\",\n    \"city_ascii\": \"Mataram\",\n    \"lat\": -8.5833,\n    \"lng\": 116.1167,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Nusa Tenggara Barat\",\n    \"capital\": \"admin\",\n    \"population\": 408900.0,\n    \"id\": 1360021952\n  },\n  {\n    \"city\": \"Tasikmalaya\",\n    \"city_ascii\": \"Tasikmalaya\",\n    \"lat\": -7.3161,\n    \"lng\": 108.1975,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Barat\",\n    \"capital\": null,\n    \"population\": 678027.0,\n    \"id\": 1360027771\n  },\n  {\n    \"city\": \"Sangereng\",\n    \"city_ascii\": \"Sangereng\",\n    \"lat\": -6.2889,\n    \"lng\": 106.7181,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Barat\",\n    \"capital\": null,\n    \"population\": 1644899.0,\n    \"id\": 1360029147\n  },\n  {\n    \"city\": \"Makassar\",\n    \"city_ascii\": \"Makassar\",\n    \"lat\": -5.1619,\n    \"lng\": 119.4362,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Sulawesi Selatan\",\n    \"capital\": \"admin\",\n    \"population\": 1338663.0,\n    \"id\": 1360051337\n  },\n  {\n    \"city\": \"Malang\",\n    \"city_ascii\": \"Malang\",\n    \"lat\": -7.98,\n    \"lng\": 112.62,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Timur\",\n    \"capital\": null,\n    \"population\": 2795209.0,\n    \"id\": 1360141408\n  },\n  {\n    \"city\": \"Cimahi\",\n    \"city_ascii\": \"Cimahi\",\n    \"lat\": -6.8712,\n    \"lng\": 107.5548,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Barat\",\n    \"capital\": null,\n    \"population\": 586580.0,\n    \"id\": 1360181436\n  },\n  {\n    \"city\": \"Bengkulu\",\n    \"city_ascii\": \"Bengkulu\",\n    \"lat\": -3.7956,\n    \"lng\": 102.2592,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Bengkulu\",\n    \"capital\": \"admin\",\n    \"population\": 360495.0,\n    \"id\": 1360191448\n  },\n  {\n    \"city\": \"Bandar Lampung\",\n    \"city_ascii\": \"Bandar Lampung\",\n    \"lat\": -5.45,\n    \"lng\": 105.2667,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Lampung\",\n    \"capital\": \"admin\",\n    \"population\": 1166761.0,\n    \"id\": 1360243491\n  },\n  {\n    \"city\": \"Bandung\",\n    \"city_ascii\": \"Bandung\",\n    \"lat\": -6.912,\n    \"lng\": 107.6097,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Barat\",\n    \"capital\": \"admin\",\n    \"population\": 432557.0,\n    \"id\": 1360313023\n  },\n  {\n    \"city\": \"Serang\",\n    \"city_ascii\": \"Serang\",\n    \"lat\": -6.12,\n    \"lng\": 106.1503,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Banten\",\n    \"capital\": \"admin\",\n    \"population\": 613356.0,\n    \"id\": 1360329102\n  },\n  {\n    \"city\": \"Yogyakarta\",\n    \"city_ascii\": \"Yogyakarta\",\n    \"lat\": -7.8014,\n    \"lng\": 110.3644,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Yogyakarta\",\n    \"capital\": \"admin\",\n    \"population\": 422732.0,\n    \"id\": 1360384833\n  },\n  {\n    \"city\": \"Bagam\",\n    \"city_ascii\": \"Bagam\",\n    \"lat\": 1.0833,\n    \"lng\": 104.0333,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Kepulauan Riau\",\n    \"capital\": null,\n    \"population\": 1230097.0,\n    \"id\": 1360405604\n  },\n  {\n    \"city\": \"Pekanbaru\",\n    \"city_ascii\": \"Pekanbaru\",\n    \"lat\": 0.5092,\n    \"lng\": 101.4453,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Riau\",\n    \"capital\": \"admin\",\n    \"population\": 983356.0,\n    \"id\": 1360422679\n  },\n  {\n    \"city\": \"Surabaya\",\n    \"city_ascii\": \"Surabaya\",\n    \"lat\": -7.2458,\n    \"lng\": 112.7378,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Timur\",\n    \"capital\": \"admin\",\n    \"population\": 6499000.0,\n    \"id\": 1360484663\n  },\n  {\n    \"city\": \"Balikpapan\",\n    \"city_ascii\": \"Balikpapan\",\n    \"lat\": -1.2768,\n    \"lng\": 116.8277,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Kalimantan Timur\",\n    \"capital\": null,\n    \"population\": 598043.0,\n    \"id\": 1360500922\n  },\n  {\n    \"city\": \"Cilacap\",\n    \"city_ascii\": \"Cilacap\",\n    \"lat\": -7.7167,\n    \"lng\": 109.017,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Tengah\",\n    \"capital\": \"minor\",\n    \"population\": 1174964.0,\n    \"id\": 1360503809\n  },\n  {\n    \"city\": \"Jayapura\",\n    \"city_ascii\": \"Jayapura\",\n    \"lat\": -2.533,\n    \"lng\": 140.717,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Papua\",\n    \"capital\": \"admin\",\n    \"population\": 413283.0,\n    \"id\": 1360517692\n  },\n  {\n    \"city\": \"Palu\",\n    \"city_ascii\": \"Palu\",\n    \"lat\": -0.895,\n    \"lng\": 119.8594,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Sulawesi Tengah\",\n    \"capital\": \"admin\",\n    \"population\": 359350.0,\n    \"id\": 1360518272\n  },\n  {\n    \"city\": \"Medan\",\n    \"city_ascii\": \"Medan\",\n    \"lat\": 3.5894,\n    \"lng\": 98.6739,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Sumatera Utara\",\n    \"capital\": \"admin\",\n    \"population\": 3632000.0,\n    \"id\": 1360543171\n  },\n  {\n    \"city\": \"Sumedang\",\n    \"city_ascii\": \"Sumedang\",\n    \"lat\": -6.84,\n    \"lng\": 107.9208,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Barat\",\n    \"capital\": null,\n    \"population\": 1240000.0,\n    \"id\": 1360564479\n  },\n  {\n    \"city\": \"Cilegon\",\n    \"city_ascii\": \"Cilegon\",\n    \"lat\": -6.0027,\n    \"lng\": 106.0112,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Banten\",\n    \"capital\": null,\n    \"population\": 387543.0,\n    \"id\": 1360643410\n  },\n  {\n    \"city\": \"Jambi\",\n    \"city_ascii\": \"Jambi\",\n    \"lat\": -1.59,\n    \"lng\": 103.61,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jambi\",\n    \"capital\": \"admin\",\n    \"population\": 612162.0,\n    \"id\": 1360645580\n  },\n  {\n    \"city\": \"Samarinda\",\n    \"city_ascii\": \"Samarinda\",\n    \"lat\": -0.5,\n    \"lng\": 117.1378,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Kalimantan Timur\",\n    \"capital\": \"admin\",\n    \"population\": 753370.0,\n    \"id\": 1360684979\n  },\n  {\n    \"city\": \"Banjarmasin\",\n    \"city_ascii\": \"Banjarmasin\",\n    \"lat\": -3.32,\n    \"lng\": 114.5925,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Kalimantan Selatan\",\n    \"capital\": \"admin\",\n    \"population\": 692793.0,\n    \"id\": 1360685223\n  },\n  {\n    \"city\": \"Kupang\",\n    \"city_ascii\": \"Kupang\",\n    \"lat\": -10.1702,\n    \"lng\": 123.6077,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Nusa Tenggara Timur\",\n    \"capital\": \"admin\",\n    \"population\": 433970.0,\n    \"id\": 1360696757\n  },\n  {\n    \"city\": \"Jepara\",\n    \"city_ascii\": \"Jepara\",\n    \"lat\": -6.5333,\n    \"lng\": 110.6667,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Tengah\",\n    \"capital\": \"minor\",\n    \"population\": 1257912.0,\n    \"id\": 1360703818\n  },\n  {\n    \"city\": \"Cibinong\",\n    \"city_ascii\": \"Cibinong\",\n    \"lat\": -6.485,\n    \"lng\": 106.842,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Barat\",\n    \"capital\": \"minor\",\n    \"population\": 363424.0,\n    \"id\": 1360730847\n  },\n  {\n    \"city\": \"Semarang\",\n    \"city_ascii\": \"Semarang\",\n    \"lat\": -6.9667,\n    \"lng\": 110.4167,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Tengah\",\n    \"capital\": \"admin\",\n    \"population\": 1621384.0,\n    \"id\": 1360745537\n  },\n  {\n    \"city\": \"Ambon\",\n    \"city_ascii\": \"Ambon\",\n    \"lat\": -3.7,\n    \"lng\": 128.1667,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Maluku\",\n    \"capital\": \"admin\",\n    \"population\": 372249.0,\n    \"id\": 1360756802\n  },\n  {\n    \"city\": \"Jakarta\",\n    \"city_ascii\": \"Jakarta\",\n    \"lat\": -6.175,\n    \"lng\": 106.8275,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jakarta\",\n    \"capital\": \"primary\",\n    \"population\": 33756000.0,\n    \"id\": 1360771077\n  },\n  {\n    \"city\": \"Manado\",\n    \"city_ascii\": \"Manado\",\n    \"lat\": 1.4931,\n    \"lng\": 124.8413,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Sulawesi Utara\",\n    \"capital\": \"admin\",\n    \"population\": 461636.0,\n    \"id\": 1360771278\n  },\n  {\n    \"city\": \"Bogor\",\n    \"city_ascii\": \"Bogor\",\n    \"lat\": -6.5966,\n    \"lng\": 106.7972,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Barat\",\n    \"capital\": null,\n    \"population\": 1030720.0,\n    \"id\": 1360771925\n  },\n  {\n    \"city\": \"Denpasar\",\n    \"city_ascii\": \"Denpasar\",\n    \"lat\": -8.65,\n    \"lng\": 115.2167,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Bali\",\n    \"capital\": \"admin\",\n    \"population\": 1779122.0,\n    \"id\": 1360848527\n  },\n  {\n    \"city\": \"Surakarta\",\n    \"city_ascii\": \"Surakarta\",\n    \"lat\": -7.5667,\n    \"lng\": 110.8167,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Tengah\",\n    \"capital\": null,\n    \"population\": 552118.0,\n    \"id\": 1360853933\n  },\n  {\n    \"city\": \"Padang\",\n    \"city_ascii\": \"Padang\",\n    \"lat\": -0.95,\n    \"lng\": 100.3531,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Sumatera Barat\",\n    \"capital\": \"admin\",\n    \"population\": 914970.0,\n    \"id\": 1360900986\n  },\n  {\n    \"city\": \"Palembang\",\n    \"city_ascii\": \"Palembang\",\n    \"lat\": -2.9861,\n    \"lng\": 104.7556,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Sumatera Selatan\",\n    \"capital\": \"admin\",\n    \"population\": 1535952.0,\n    \"id\": 1360902897\n  },\n  {\n    \"city\": \"Depok\",\n    \"city_ascii\": \"Depok\",\n    \"lat\": -6.394,\n    \"lng\": 106.8225,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Jawa Barat\",\n    \"capital\": null,\n    \"population\": 2330333.0,\n    \"id\": 1360962899\n  },\n  {\n    \"city\": \"Pontianak\",\n    \"city_ascii\": \"Pontianak\",\n    \"lat\": -0.0206,\n    \"lng\": 109.3414,\n    \"country\": \"Indonesia\",\n    \"iso2\": \"ID\",\n    \"iso3\": \"IDN\",\n    \"admin_name\": \"Kalimantan Barat\",\n    \"capital\": \"admin\",\n    \"population\": 618388.0,\n    \"id\": 1360992394\n  },\n  {\n    \"city\": \"Kāshān\",\n    \"city_ascii\": \"Kashan\",\n    \"lat\": 33.9833,\n    \"lng\": 51.4333,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Eşfahān\",\n    \"capital\": \"minor\",\n    \"population\": 5000000.0,\n    \"id\": 1364006067\n  },\n  {\n    \"city\": \"Eşfahān\",\n    \"city_ascii\": \"Esfahan\",\n    \"lat\": 32.6447,\n    \"lng\": 51.6675,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Eşfahān\",\n    \"capital\": \"admin\",\n    \"population\": 2219343.0,\n    \"id\": 1364023865\n  },\n  {\n    \"city\": \"Zāhedān\",\n    \"city_ascii\": \"Zahedan\",\n    \"lat\": 29.4964,\n    \"lng\": 60.8628,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Sīstān va Balūchestān\",\n    \"capital\": \"admin\",\n    \"population\": 587730.0,\n    \"id\": 1364072353\n  },\n  {\n    \"city\": \"Qazvīn\",\n    \"city_ascii\": \"Qazvin\",\n    \"lat\": 36.2667,\n    \"lng\": 50.0,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Qazvīn\",\n    \"capital\": \"admin\",\n    \"population\": 402748.0,\n    \"id\": 1364073420\n  },\n  {\n    \"city\": \"Bandar ‘Abbās\",\n    \"city_ascii\": \"Bandar `Abbas\",\n    \"lat\": 27.1833,\n    \"lng\": 56.2667,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Hormozgān\",\n    \"capital\": \"admin\",\n    \"population\": 526648.0,\n    \"id\": 1364120623\n  },\n  {\n    \"city\": \"Mashhad\",\n    \"city_ascii\": \"Mashhad\",\n    \"lat\": 36.3,\n    \"lng\": 59.6,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Khorāsān-e Raẕavī\",\n    \"capital\": \"admin\",\n    \"population\": 3372090.0,\n    \"id\": 1364123206\n  },\n  {\n    \"city\": \"Hamadān\",\n    \"city_ascii\": \"Hamadan\",\n    \"lat\": 34.8064,\n    \"lng\": 48.5161,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Hamadān\",\n    \"capital\": \"admin\",\n    \"population\": 554406.0,\n    \"id\": 1364126377\n  },\n  {\n    \"city\": \"Tabrīz\",\n    \"city_ascii\": \"Tabriz\",\n    \"lat\": 38.0814,\n    \"lng\": 46.3006,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Āz̄arbāyjān-e Sharqī\",\n    \"capital\": \"admin\",\n    \"population\": 1558693.0,\n    \"id\": 1364141756\n  },\n  {\n    \"city\": \"Orūmīyeh\",\n    \"city_ascii\": \"Orumiyeh\",\n    \"lat\": 37.5486,\n    \"lng\": 45.0675,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Āz̄arbāyjān-e Gharbī\",\n    \"capital\": \"admin\",\n    \"population\": 736224.0,\n    \"id\": 1364158221\n  },\n  {\n    \"city\": \"Sanandaj\",\n    \"city_ascii\": \"Sanandaj\",\n    \"lat\": 35.3144,\n    \"lng\": 46.9922,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Kordestān\",\n    \"capital\": \"admin\",\n    \"population\": 412767.0,\n    \"id\": 1364178783\n  },\n  {\n    \"city\": \"Karaj\",\n    \"city_ascii\": \"Karaj\",\n    \"lat\": 35.8272,\n    \"lng\": 50.9489,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Alborz\",\n    \"capital\": \"admin\",\n    \"population\": 1973470.0,\n    \"id\": 1364258511\n  },\n  {\n    \"city\": \"Tehran\",\n    \"city_ascii\": \"Tehran\",\n    \"lat\": 35.6892,\n    \"lng\": 51.3889,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Tehrān\",\n    \"capital\": \"primary\",\n    \"population\": 14148000.0,\n    \"id\": 1364305026\n  },\n  {\n    \"city\": \"Zanjān\",\n    \"city_ascii\": \"Zanjan\",\n    \"lat\": 36.6789,\n    \"lng\": 48.5056,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Zanjān\",\n    \"capital\": \"admin\",\n    \"population\": 433475.0,\n    \"id\": 1364312712\n  },\n  {\n    \"city\": \"Ahvāz\",\n    \"city_ascii\": \"Ahvaz\",\n    \"lat\": 31.3203,\n    \"lng\": 48.6692,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Khūzestān\",\n    \"capital\": \"admin\",\n    \"population\": 1261042.0,\n    \"id\": 1364350188\n  },\n  {\n    \"city\": \"Yazd\",\n    \"city_ascii\": \"Yazd\",\n    \"lat\": 31.8822,\n    \"lng\": 54.3397,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Yazd\",\n    \"capital\": \"admin\",\n    \"population\": 529673.0,\n    \"id\": 1364429875\n  },\n  {\n    \"city\": \"Shīrāz\",\n    \"city_ascii\": \"Shiraz\",\n    \"lat\": 29.61,\n    \"lng\": 52.5425,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Fārs\",\n    \"capital\": \"admin\",\n    \"population\": 1565572.0,\n    \"id\": 1364432238\n  },\n  {\n    \"city\": \"Ardabīl\",\n    \"city_ascii\": \"Ardabil\",\n    \"lat\": 38.2425,\n    \"lng\": 48.29,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Ardabīl\",\n    \"capital\": \"admin\",\n    \"population\": 529374.0,\n    \"id\": 1364437616\n  },\n  {\n    \"city\": \"Kermānshāh\",\n    \"city_ascii\": \"Kermanshah\",\n    \"lat\": 34.3142,\n    \"lng\": 47.065,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Kermānshāh\",\n    \"capital\": \"admin\",\n    \"population\": 952285.0,\n    \"id\": 1364535690\n  },\n  {\n    \"city\": \"Khorramābād\",\n    \"city_ascii\": \"Khorramabad\",\n    \"lat\": 33.4878,\n    \"lng\": 48.3558,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Lorestān\",\n    \"capital\": \"admin\",\n    \"population\": 373416.0,\n    \"id\": 1364548806\n  },\n  {\n    \"city\": \"Kermān\",\n    \"city_ascii\": \"Kerman\",\n    \"lat\": 30.2833,\n    \"lng\": 57.0833,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Kermān\",\n    \"capital\": \"admin\",\n    \"population\": 738374.0,\n    \"id\": 1364554896\n  },\n  {\n    \"city\": \"Arāk\",\n    \"city_ascii\": \"Arak\",\n    \"lat\": 34.0917,\n    \"lng\": 49.6892,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Markazī\",\n    \"capital\": \"admin\",\n    \"population\": 520944.0,\n    \"id\": 1364624691\n  },\n  {\n    \"city\": \"Rasht\",\n    \"city_ascii\": \"Rasht\",\n    \"lat\": 37.2808,\n    \"lng\": 49.5831,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Gīlān\",\n    \"capital\": \"admin\",\n    \"population\": 679995.0,\n    \"id\": 1364630382\n  },\n  {\n    \"city\": \"Qom\",\n    \"city_ascii\": \"Qom\",\n    \"lat\": 34.64,\n    \"lng\": 50.8764,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Qom\",\n    \"capital\": \"admin\",\n    \"population\": 1201158.0,\n    \"id\": 1364701633\n  },\n  {\n    \"city\": \"Madan\",\n    \"city_ascii\": \"Madan\",\n    \"lat\": 30.3392,\n    \"lng\": 48.3042,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Khūzestān\",\n    \"capital\": null,\n    \"population\": 370180.0,\n    \"id\": 1364708556\n  },\n  {\n    \"city\": \"Gorgān\",\n    \"city_ascii\": \"Gorgan\",\n    \"lat\": 36.8386,\n    \"lng\": 54.4347,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Golestān\",\n    \"capital\": \"admin\",\n    \"population\": 350676.0,\n    \"id\": 1364802450\n  },\n  {\n    \"city\": \"Eslāmshahr\",\n    \"city_ascii\": \"Eslamshahr\",\n    \"lat\": 35.5606,\n    \"lng\": 51.2347,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Tehrān\",\n    \"capital\": \"minor\",\n    \"population\": 448129.0,\n    \"id\": 1364870126\n  },\n  {\n    \"city\": \"Bahār\",\n    \"city_ascii\": \"Bahar\",\n    \"lat\": 34.9072,\n    \"lng\": 48.4414,\n    \"country\": \"Iran\",\n    \"iso2\": \"IR\",\n    \"iso3\": \"IRN\",\n    \"admin_name\": \"Hamadān\",\n    \"capital\": \"minor\",\n    \"population\": 673405.0,\n    \"id\": 1364891653\n  },\n  {\n    \"city\": \"An Najaf\",\n    \"city_ascii\": \"An Najaf\",\n    \"lat\": 32.0,\n    \"lng\": 44.33,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"An Najaf\",\n    \"capital\": \"admin\",\n    \"population\": 724700.0,\n    \"id\": 1368003357\n  },\n  {\n    \"city\": \"Az Zubayr\",\n    \"city_ascii\": \"Az Zubayr\",\n    \"lat\": 30.3833,\n    \"lng\": 47.7,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Al Başrah\",\n    \"capital\": \"minor\",\n    \"population\": 370000.0,\n    \"id\": 1368147923\n  },\n  {\n    \"city\": \"Mosul\",\n    \"city_ascii\": \"Mosul\",\n    \"lat\": 36.34,\n    \"lng\": 43.13,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Nīnawá\",\n    \"capital\": \"admin\",\n    \"population\": 1694000.0,\n    \"id\": 1368194914\n  },\n  {\n    \"city\": \"An Nāşirīyah\",\n    \"city_ascii\": \"An Nasiriyah\",\n    \"lat\": 31.0439,\n    \"lng\": 46.2575,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Dhī Qār\",\n    \"capital\": \"admin\",\n    \"population\": 541600.0,\n    \"id\": 1368273311\n  },\n  {\n    \"city\": \"Al ‘Amārah\",\n    \"city_ascii\": \"Al `Amarah\",\n    \"lat\": 31.8333,\n    \"lng\": 47.15,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Maysān\",\n    \"capital\": \"admin\",\n    \"population\": 511500.0,\n    \"id\": 1368336235\n  },\n  {\n    \"city\": \"Kirkuk\",\n    \"city_ascii\": \"Kirkuk\",\n    \"lat\": 35.4667,\n    \"lng\": 44.3167,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Karkūk\",\n    \"capital\": \"admin\",\n    \"population\": 975000.0,\n    \"id\": 1368344172\n  },\n  {\n    \"city\": \"Ba‘qūbah\",\n    \"city_ascii\": \"Ba`qubah\",\n    \"lat\": 33.75,\n    \"lng\": 44.6333,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Diyālá\",\n    \"capital\": \"admin\",\n    \"population\": 467900.0,\n    \"id\": 1368444902\n  },\n  {\n    \"city\": \"Erbil\",\n    \"city_ascii\": \"Erbil\",\n    \"lat\": 36.1912,\n    \"lng\": 44.0092,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Arbīl\",\n    \"capital\": \"admin\",\n    \"population\": 846000.0,\n    \"id\": 1368578192\n  },\n  {\n    \"city\": \"Baghdad\",\n    \"city_ascii\": \"Baghdad\",\n    \"lat\": 33.3153,\n    \"lng\": 44.3661,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Baghdād\",\n    \"capital\": \"primary\",\n    \"population\": 6183000.0,\n    \"id\": 1368596238\n  },\n  {\n    \"city\": \"Karbalā’\",\n    \"city_ascii\": \"Karbala'\",\n    \"lat\": 32.6167,\n    \"lng\": 44.0333,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Karbalā’\",\n    \"capital\": \"admin\",\n    \"population\": 690100.0,\n    \"id\": 1368597794\n  },\n  {\n    \"city\": \"Al Başrah\",\n    \"city_ascii\": \"Al Basrah\",\n    \"lat\": 30.515,\n    \"lng\": 47.81,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Al Başrah\",\n    \"capital\": \"admin\",\n    \"population\": 1326564.0,\n    \"id\": 1368714645\n  },\n  {\n    \"city\": \"As Sulaymānīyah\",\n    \"city_ascii\": \"As Sulaymaniyah\",\n    \"lat\": 35.5572,\n    \"lng\": 45.4356,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"As Sulaymānīyah\",\n    \"capital\": \"admin\",\n    \"population\": 878146.0,\n    \"id\": 1368735317\n  },\n  {\n    \"city\": \"Ar Ramādī\",\n    \"city_ascii\": \"Ar Ramadi\",\n    \"lat\": 33.4258,\n    \"lng\": 43.2992,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Al Anbār\",\n    \"capital\": \"admin\",\n    \"population\": 874543.0,\n    \"id\": 1368838855\n  },\n  {\n    \"city\": \"Ad Dīwānīyah\",\n    \"city_ascii\": \"Ad Diwaniyah\",\n    \"lat\": 31.9892,\n    \"lng\": 44.9247,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Al Qādisīyah\",\n    \"capital\": \"admin\",\n    \"population\": 391600.0,\n    \"id\": 1368864006\n  },\n  {\n    \"city\": \"Al Ḩillah\",\n    \"city_ascii\": \"Al Hillah\",\n    \"lat\": 32.4833,\n    \"lng\": 44.4333,\n    \"country\": \"Iraq\",\n    \"iso2\": \"IQ\",\n    \"iso3\": \"IRQ\",\n    \"admin_name\": \"Bābil\",\n    \"capital\": \"admin\",\n    \"population\": 541034.0,\n    \"id\": 1368916692\n  },\n  {\n    \"city\": \"Dublin\",\n    \"city_ascii\": \"Dublin\",\n    \"lat\": 53.35,\n    \"lng\": -6.2603,\n    \"country\": \"Ireland\",\n    \"iso2\": \"IE\",\n    \"iso3\": \"IRL\",\n    \"admin_name\": \"Dublin\",\n    \"capital\": \"primary\",\n    \"population\": 1173179.0,\n    \"id\": 1372595407\n  },\n  {\n    \"city\": \"Haifa\",\n    \"city_ascii\": \"Haifa\",\n    \"lat\": 32.8192,\n    \"lng\": 34.9992,\n    \"country\": \"Israel\",\n    \"iso2\": \"IL\",\n    \"iso3\": \"ISR\",\n    \"admin_name\": \"Haifa\",\n    \"capital\": \"admin\",\n    \"population\": 600000.0,\n    \"id\": 1376133727\n  },\n  {\n    \"city\": \"Jerusalem\",\n    \"city_ascii\": \"Jerusalem\",\n    \"lat\": 31.7784,\n    \"lng\": 35.2066,\n    \"country\": \"Israel\",\n    \"iso2\": \"IL\",\n    \"iso3\": \"ISR\",\n    \"admin_name\": \"Jerusalem\",\n    \"capital\": \"primary\",\n    \"population\": 919438.0,\n    \"id\": 1376261644\n  },\n  {\n    \"city\": \"Tel Aviv-Yafo\",\n    \"city_ascii\": \"Tel Aviv-Yafo\",\n    \"lat\": 32.08,\n    \"lng\": 34.78,\n    \"country\": \"Israel\",\n    \"iso2\": \"IL\",\n    \"iso3\": \"ISR\",\n    \"admin_name\": \"Tel Aviv\",\n    \"capital\": \"admin\",\n    \"population\": 1388400.0,\n    \"id\": 1376401542\n  },\n  {\n    \"city\": \"Bologna\",\n    \"city_ascii\": \"Bologna\",\n    \"lat\": 44.4939,\n    \"lng\": 11.3428,\n    \"country\": \"Italy\",\n    \"iso2\": \"IT\",\n    \"iso3\": \"ITA\",\n    \"admin_name\": \"Emilia-Romagna\",\n    \"capital\": \"admin\",\n    \"population\": 392564.0,\n    \"id\": 1380202039\n  },\n  {\n    \"city\": \"Turin\",\n    \"city_ascii\": \"Turin\",\n    \"lat\": 45.0792,\n    \"lng\": 7.6761,\n    \"country\": \"Italy\",\n    \"iso2\": \"IT\",\n    \"iso3\": \"ITA\",\n    \"admin_name\": \"Piedmont\",\n    \"capital\": \"admin\",\n    \"population\": 870952.0,\n    \"id\": 1380244627\n  },\n  {\n    \"city\": \"Rome\",\n    \"city_ascii\": \"Rome\",\n    \"lat\": 41.8931,\n    \"lng\": 12.4828,\n    \"country\": \"Italy\",\n    \"iso2\": \"IT\",\n    \"iso3\": \"ITA\",\n    \"admin_name\": \"Lazio\",\n    \"capital\": \"primary\",\n    \"population\": 2872800.0,\n    \"id\": 1380382862\n  },\n  {\n    \"city\": \"Palermo\",\n    \"city_ascii\": \"Palermo\",\n    \"lat\": 38.1157,\n    \"lng\": 13.3613,\n    \"country\": \"Italy\",\n    \"iso2\": \"IT\",\n    \"iso3\": \"ITA\",\n    \"admin_name\": \"Sicilia\",\n    \"capital\": \"admin\",\n    \"population\": 668405.0,\n    \"id\": 1380428434\n  },\n  {\n    \"city\": \"Naples\",\n    \"city_ascii\": \"Naples\",\n    \"lat\": 40.8333,\n    \"lng\": 14.25,\n    \"country\": \"Italy\",\n    \"iso2\": \"IT\",\n    \"iso3\": \"ITA\",\n    \"admin_name\": \"Campania\",\n    \"capital\": \"admin\",\n    \"population\": 966144.0,\n    \"id\": 1380646673\n  },\n  {\n    \"city\": \"Genoa\",\n    \"city_ascii\": \"Genoa\",\n    \"lat\": 44.4111,\n    \"lng\": 8.9328,\n    \"country\": \"Italy\",\n    \"iso2\": \"IT\",\n    \"iso3\": \"ITA\",\n    \"admin_name\": \"Liguria\",\n    \"capital\": \"admin\",\n    \"population\": 580097.0,\n    \"id\": 1380716540\n  },\n  {\n    \"city\": \"Milan\",\n    \"city_ascii\": \"Milan\",\n    \"lat\": 45.4669,\n    \"lng\": 9.19,\n    \"country\": \"Italy\",\n    \"iso2\": \"IT\",\n    \"iso3\": \"ITA\",\n    \"admin_name\": \"Lombardy\",\n    \"capital\": \"admin\",\n    \"population\": 1366180.0,\n    \"id\": 1380724377\n  },\n  {\n    \"city\": \"Florence\",\n    \"city_ascii\": \"Florence\",\n    \"lat\": 43.7714,\n    \"lng\": 11.2542,\n    \"country\": \"Italy\",\n    \"iso2\": \"IT\",\n    \"iso3\": \"ITA\",\n    \"admin_name\": \"Tuscany\",\n    \"capital\": \"admin\",\n    \"population\": 380948.0,\n    \"id\": 1380726561\n  },\n  {\n    \"city\": \"Abidjan\",\n    \"city_ascii\": \"Abidjan\",\n    \"lat\": 5.3167,\n    \"lng\": -4.0333,\n    \"country\": \"Côte d'Ivoire\",\n    \"iso2\": \"CI\",\n    \"iso3\": \"CIV\",\n    \"admin_name\": \"Abidjan\",\n    \"capital\": \"primary\",\n    \"population\": 4980000.0,\n    \"id\": 1384207980\n  },\n  {\n    \"city\": \"Cocody\",\n    \"city_ascii\": \"Cocody\",\n    \"lat\": 5.35,\n    \"lng\": -3.9667,\n    \"country\": \"Côte d'Ivoire\",\n    \"iso2\": \"CI\",\n    \"iso3\": \"CIV\",\n    \"admin_name\": \"Abidjan\",\n    \"capital\": null,\n    \"population\": 692583.0,\n    \"id\": 1384351512\n  },\n  {\n    \"city\": \"San-Pédro\",\n    \"city_ascii\": \"San-Pedro\",\n    \"lat\": 4.75,\n    \"lng\": -6.6333,\n    \"country\": \"Côte d'Ivoire\",\n    \"iso2\": \"CI\",\n    \"iso3\": \"CIV\",\n    \"admin_name\": \"Bas-Sassandra\",\n    \"capital\": \"admin\",\n    \"population\": 390654.0,\n    \"id\": 1384436547\n  },\n  {\n    \"city\": \"Port-Bouët\",\n    \"city_ascii\": \"Port-Bouet\",\n    \"lat\": 5.2667,\n    \"lng\": -3.9,\n    \"country\": \"Côte d'Ivoire\",\n    \"iso2\": \"CI\",\n    \"iso3\": \"CIV\",\n    \"admin_name\": \"Abidjan\",\n    \"capital\": null,\n    \"population\": 618795.0,\n    \"id\": 1384512844\n  },\n  {\n    \"city\": \"Daloa\",\n    \"city_ascii\": \"Daloa\",\n    \"lat\": 6.8833,\n    \"lng\": -6.45,\n    \"country\": \"Côte d'Ivoire\",\n    \"iso2\": \"CI\",\n    \"iso3\": \"CIV\",\n    \"admin_name\": \"Sassandra-Marahoué\",\n    \"capital\": \"admin\",\n    \"population\": 421871.0,\n    \"id\": 1384564974\n  },\n  {\n    \"city\": \"Yamoussoukro\",\n    \"city_ascii\": \"Yamoussoukro\",\n    \"lat\": 6.8161,\n    \"lng\": -5.2742,\n    \"country\": \"Côte d'Ivoire\",\n    \"iso2\": \"CI\",\n    \"iso3\": \"CIV\",\n    \"admin_name\": \"Yamoussoukro\",\n    \"capital\": \"primary\",\n    \"population\": 355573.0,\n    \"id\": 1384683557\n  },\n  {\n    \"city\": \"Yopougon\",\n    \"city_ascii\": \"Yopougon\",\n    \"lat\": 5.3167,\n    \"lng\": -4.0667,\n    \"country\": \"Côte d'Ivoire\",\n    \"iso2\": \"CI\",\n    \"iso3\": \"CIV\",\n    \"admin_name\": \"Abidjan\",\n    \"capital\": null,\n    \"population\": 1571065.0,\n    \"id\": 1384759584\n  },\n  {\n    \"city\": \"Koumassi\",\n    \"city_ascii\": \"Koumassi\",\n    \"lat\": 5.3,\n    \"lng\": -3.95,\n    \"country\": \"Côte d'Ivoire\",\n    \"iso2\": \"CI\",\n    \"iso3\": \"CIV\",\n    \"admin_name\": \"Abidjan\",\n    \"capital\": null,\n    \"population\": 412282.0,\n    \"id\": 1384863297\n  },\n  {\n    \"city\": \"Bouaké\",\n    \"city_ascii\": \"Bouake\",\n    \"lat\": 7.6833,\n    \"lng\": -5.0167,\n    \"country\": \"Côte d'Ivoire\",\n    \"iso2\": \"CI\",\n    \"iso3\": \"CIV\",\n    \"admin_name\": \"Vallée du Bandama\",\n    \"capital\": \"admin\",\n    \"population\": 659233.0,\n    \"id\": 1384983838\n  },\n  {\n    \"city\": \"Kingston\",\n    \"city_ascii\": \"Kingston\",\n    \"lat\": 17.9714,\n    \"lng\": -76.7931,\n    \"country\": \"Jamaica\",\n    \"iso2\": \"JM\",\n    \"iso3\": \"JAM\",\n    \"admin_name\": \"Kingston\",\n    \"capital\": \"primary\",\n    \"population\": 580000.0,\n    \"id\": 1388709177\n  },\n  {\n    \"city\": \"Sapporo\",\n    \"city_ascii\": \"Sapporo\",\n    \"lat\": 43.0667,\n    \"lng\": 141.35,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Hokkaidō\",\n    \"capital\": \"admin\",\n    \"population\": 1961690.0,\n    \"id\": 1392000195\n  },\n  {\n    \"city\": \"Takasaki\",\n    \"city_ascii\": \"Takasaki\",\n    \"lat\": 36.3219,\n    \"lng\": 139.0033,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Gunma\",\n    \"capital\": null,\n    \"population\": 372639.0,\n    \"id\": 1392000529\n  },\n  {\n    \"city\": \"Toyama\",\n    \"city_ascii\": \"Toyama\",\n    \"lat\": 36.6959,\n    \"lng\": 137.2137,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Toyama\",\n    \"capital\": \"admin\",\n    \"population\": 413028.0,\n    \"id\": 1392000560\n  },\n  {\n    \"city\": \"Takatsuki\",\n    \"city_ascii\": \"Takatsuki\",\n    \"lat\": 34.85,\n    \"lng\": 135.6167,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Ōsaka\",\n    \"capital\": null,\n    \"population\": 347496.0,\n    \"id\": 1392003061\n  },\n  {\n    \"city\": \"Suginami-ku\",\n    \"city_ascii\": \"Suginami-ku\",\n    \"lat\": 35.6995,\n    \"lng\": 139.6364,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 583609.0,\n    \"id\": 1392003090\n  },\n  {\n    \"city\": \"Kitakyūshū\",\n    \"city_ascii\": \"Kitakyushu\",\n    \"lat\": 33.8833,\n    \"lng\": 130.8833,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Fukuoka\",\n    \"capital\": null,\n    \"population\": 935084.0,\n    \"id\": 1392003140\n  },\n  {\n    \"city\": \"Himeji\",\n    \"city_ascii\": \"Himeji\",\n    \"lat\": 34.8167,\n    \"lng\": 134.6833,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Hyōgo\",\n    \"capital\": null,\n    \"population\": 527596.0,\n    \"id\": 1392003149\n  },\n  {\n    \"city\": \"Amagasaki\",\n    \"city_ascii\": \"Amagasaki\",\n    \"lat\": 34.7333,\n    \"lng\": 135.4,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Hyōgo\",\n    \"capital\": null,\n    \"population\": 450506.0,\n    \"id\": 1392003182\n  },\n  {\n    \"city\": \"Kurashiki\",\n    \"city_ascii\": \"Kurashiki\",\n    \"lat\": 34.5833,\n    \"lng\": 133.7667,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Okayama\",\n    \"capital\": null,\n    \"population\": 474862.0,\n    \"id\": 1392003246\n  },\n  {\n    \"city\": \"Toyonaka\",\n    \"city_ascii\": \"Toyonaka\",\n    \"lat\": 34.7833,\n    \"lng\": 135.4667,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Ōsaka\",\n    \"capital\": null,\n    \"population\": 401233.0,\n    \"id\": 1392003256\n  },\n  {\n    \"city\": \"Kita-ku\",\n    \"city_ascii\": \"Kita-ku\",\n    \"lat\": 35.7528,\n    \"lng\": 139.7336,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 353058.0,\n    \"id\": 1392003263\n  },\n  {\n    \"city\": \"Sakai\",\n    \"city_ascii\": \"Sakai\",\n    \"lat\": 34.5733,\n    \"lng\": 135.4831,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Ōsaka\",\n    \"capital\": null,\n    \"population\": 824408.0,\n    \"id\": 1392003291\n  },\n  {\n    \"city\": \"Shinagawa-ku\",\n    \"city_ascii\": \"Shinagawa-ku\",\n    \"lat\": 35.6092,\n    \"lng\": 139.7302,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 415729.0,\n    \"id\": 1392003304\n  },\n  {\n    \"city\": \"Kōtō-ku\",\n    \"city_ascii\": \"Koto-ku\",\n    \"lat\": 35.6728,\n    \"lng\": 139.8173,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 523117.0,\n    \"id\": 1392003346\n  },\n  {\n    \"city\": \"Kawasaki\",\n    \"city_ascii\": \"Kawasaki\",\n    \"lat\": 35.5167,\n    \"lng\": 139.7,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Kanagawa\",\n    \"capital\": null,\n    \"population\": 1539522.0,\n    \"id\": 1392003356\n  },\n  {\n    \"city\": \"Katsushika-ku\",\n    \"city_ascii\": \"Katsushika-ku\",\n    \"lat\": 35.7434,\n    \"lng\": 139.8472,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 453410.0,\n    \"id\": 1392003368\n  },\n  {\n    \"city\": \"Yokosuka\",\n    \"city_ascii\": \"Yokosuka\",\n    \"lat\": 35.25,\n    \"lng\": 139.6667,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Kanagawa\",\n    \"capital\": null,\n    \"population\": 390275.0,\n    \"id\": 1392003389\n  },\n  {\n    \"city\": \"Ōta-ku\",\n    \"city_ascii\": \"Ota-ku\",\n    \"lat\": 35.5613,\n    \"lng\": 139.716,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 737187.0,\n    \"id\": 1392003511\n  },\n  {\n    \"city\": \"Saitama\",\n    \"city_ascii\": \"Saitama\",\n    \"lat\": 35.8614,\n    \"lng\": 139.6456,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Saitama\",\n    \"capital\": \"admin\",\n    \"population\": 1325843.0,\n    \"id\": 1392017719\n  },\n  {\n    \"city\": \"Ichikawa\",\n    \"city_ascii\": \"Ichikawa\",\n    \"lat\": 35.7219,\n    \"lng\": 139.9311,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Chiba\",\n    \"capital\": null,\n    \"population\": 496657.0,\n    \"id\": 1392076347\n  },\n  {\n    \"city\": \"Ōita\",\n    \"city_ascii\": \"Oita\",\n    \"lat\": 33.2333,\n    \"lng\": 131.6067,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Ōita\",\n    \"capital\": \"admin\",\n    \"population\": 477186.0,\n    \"id\": 1392081193\n  },\n  {\n    \"city\": \"Aomori\",\n    \"city_ascii\": \"Aomori\",\n    \"lat\": 40.8223,\n    \"lng\": 140.7307,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Aomori\",\n    \"capital\": \"admin\",\n    \"population\": 425962.0,\n    \"id\": 1392083898\n  },\n  {\n    \"city\": \"Nerima\",\n    \"city_ascii\": \"Nerima\",\n    \"lat\": 35.7355,\n    \"lng\": 139.6517,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 742463.0,\n    \"id\": 1392093402\n  },\n  {\n    \"city\": \"Gifu\",\n    \"city_ascii\": \"Gifu\",\n    \"lat\": 35.4232,\n    \"lng\": 136.7608,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Gifu\",\n    \"capital\": \"admin\",\n    \"population\": 400118.0,\n    \"id\": 1392097787\n  },\n  {\n    \"city\": \"Kumamoto\",\n    \"city_ascii\": \"Kumamoto\",\n    \"lat\": 32.8031,\n    \"lng\": 130.7078,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Kumamoto\",\n    \"capital\": \"admin\",\n    \"population\": 738385.0,\n    \"id\": 1392106283\n  },\n  {\n    \"city\": \"Chiba\",\n    \"city_ascii\": \"Chiba\",\n    \"lat\": 35.6073,\n    \"lng\": 140.1064,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Chiba\",\n    \"capital\": \"admin\",\n    \"population\": 981738.0,\n    \"id\": 1392107144\n  },\n  {\n    \"city\": \"Nishinomiya-hama\",\n    \"city_ascii\": \"Nishinomiya-hama\",\n    \"lat\": 34.7376,\n    \"lng\": 135.3416,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Hyōgo\",\n    \"capital\": null,\n    \"population\": 487010.0,\n    \"id\": 1392114116\n  },\n  {\n    \"city\": \"Higashi-ōsaka\",\n    \"city_ascii\": \"Higashi-osaka\",\n    \"lat\": 34.6794,\n    \"lng\": 135.6008,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Ōsaka\",\n    \"capital\": null,\n    \"population\": 490819.0,\n    \"id\": 1392117396\n  },\n  {\n    \"city\": \"Yokohama\",\n    \"city_ascii\": \"Yokohama\",\n    \"lat\": 35.4442,\n    \"lng\": 139.6381,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Kanagawa\",\n    \"capital\": \"admin\",\n    \"population\": 3757630.0,\n    \"id\": 1392118339\n  },\n  {\n    \"city\": \"Kagoshima\",\n    \"city_ascii\": \"Kagoshima\",\n    \"lat\": 31.6,\n    \"lng\": 130.55,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Kagoshima\",\n    \"capital\": \"admin\",\n    \"population\": 593754.0,\n    \"id\": 1392120675\n  },\n  {\n    \"city\": \"Kashiwa\",\n    \"city_ascii\": \"Kashiwa\",\n    \"lat\": 35.8676,\n    \"lng\": 139.9758,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Chiba\",\n    \"capital\": null,\n    \"population\": 433941.0,\n    \"id\": 1392133166\n  },\n  {\n    \"city\": \"Edogawa\",\n    \"city_ascii\": \"Edogawa\",\n    \"lat\": 35.7066,\n    \"lng\": 139.8683,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Chiba\",\n    \"capital\": null,\n    \"population\": 697932.0,\n    \"id\": 1392135698\n  },\n  {\n    \"city\": \"Nagasaki\",\n    \"city_ascii\": \"Nagasaki\",\n    \"lat\": 32.7447,\n    \"lng\": 129.8736,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Nagasaki\",\n    \"capital\": \"admin\",\n    \"population\": 404656.0,\n    \"id\": 1392162566\n  },\n  {\n    \"city\": \"Ōtsu\",\n    \"city_ascii\": \"Otsu\",\n    \"lat\": 35.0167,\n    \"lng\": 135.85,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Shiga\",\n    \"capital\": \"admin\",\n    \"population\": 342607.0,\n    \"id\": 1392164106\n  },\n  {\n    \"city\": \"Hachiōji\",\n    \"city_ascii\": \"Hachioji\",\n    \"lat\": 35.6664,\n    \"lng\": 139.316,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 575721.0,\n    \"id\": 1392172935\n  },\n  {\n    \"city\": \"Hamamatsu\",\n    \"city_ascii\": \"Hamamatsu\",\n    \"lat\": 34.7108,\n    \"lng\": 137.7275,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Shizuoka\",\n    \"capital\": null,\n    \"population\": 788211.0,\n    \"id\": 1392174500\n  },\n  {\n    \"city\": \"Miyazaki\",\n    \"city_ascii\": \"Miyazaki\",\n    \"lat\": 31.9167,\n    \"lng\": 131.4167,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Miyazaki\",\n    \"capital\": \"admin\",\n    \"population\": 397476.0,\n    \"id\": 1392216224\n  },\n  {\n    \"city\": \"Matsuyama\",\n    \"city_ascii\": \"Matsuyama\",\n    \"lat\": 33.8333,\n    \"lng\": 132.7667,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Ehime\",\n    \"capital\": \"admin\",\n    \"population\": 506743.0,\n    \"id\": 1392220893\n  },\n  {\n    \"city\": \"Shizuoka\",\n    \"city_ascii\": \"Shizuoka\",\n    \"lat\": 34.9756,\n    \"lng\": 138.3828,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Shizuoka\",\n    \"capital\": \"admin\",\n    \"population\": 685589.0,\n    \"id\": 1392235505\n  },\n  {\n    \"city\": \"Tokorozawa\",\n    \"city_ascii\": \"Tokorozawa\",\n    \"lat\": 35.7996,\n    \"lng\": 139.4686,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Saitama\",\n    \"capital\": null,\n    \"population\": 341289.0,\n    \"id\": 1392340764\n  },\n  {\n    \"city\": \"Hiroshima\",\n    \"city_ascii\": \"Hiroshima\",\n    \"lat\": 34.3914,\n    \"lng\": 132.4519,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Hiroshima\",\n    \"capital\": \"admin\",\n    \"population\": 1198021.0,\n    \"id\": 1392373695\n  },\n  {\n    \"city\": \"Ichinomiya\",\n    \"city_ascii\": \"Ichinomiya\",\n    \"lat\": 35.3039,\n    \"lng\": 136.8031,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Aichi\",\n    \"capital\": null,\n    \"population\": 378681.0,\n    \"id\": 1392379530\n  },\n  {\n    \"city\": \"Nagoya\",\n    \"city_ascii\": \"Nagoya\",\n    \"lat\": 35.1833,\n    \"lng\": 136.9,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Aichi\",\n    \"capital\": \"admin\",\n    \"population\": 9197000.0,\n    \"id\": 1392407472\n  },\n  {\n    \"city\": \"Ōsaka\",\n    \"city_ascii\": \"Osaka\",\n    \"lat\": 34.6939,\n    \"lng\": 135.5022,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Ōsaka\",\n    \"capital\": \"admin\",\n    \"population\": 15126000.0,\n    \"id\": 1392419823\n  },\n  {\n    \"city\": \"Takamatsu\",\n    \"city_ascii\": \"Takamatsu\",\n    \"lat\": 34.35,\n    \"lng\": 134.05,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Kagawa\",\n    \"capital\": \"admin\",\n    \"population\": 417814.0,\n    \"id\": 1392427161\n  },\n  {\n    \"city\": \"Sendai\",\n    \"city_ascii\": \"Sendai\",\n    \"lat\": 38.2682,\n    \"lng\": 140.8694,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Miyagi\",\n    \"capital\": \"admin\",\n    \"population\": 1061177.0,\n    \"id\": 1392457903\n  },\n  {\n    \"city\": \"Adachi\",\n    \"city_ascii\": \"Adachi\",\n    \"lat\": 35.7749,\n    \"lng\": 139.8044,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 682326.0,\n    \"id\": 1392464568\n  },\n  {\n    \"city\": \"Toyohashi\",\n    \"city_ascii\": \"Toyohashi\",\n    \"lat\": 34.7692,\n    \"lng\": 137.3915,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Aichi\",\n    \"capital\": null,\n    \"population\": 371507.0,\n    \"id\": 1392482960\n  },\n  {\n    \"city\": \"Toyota\",\n    \"city_ascii\": \"Toyota\",\n    \"lat\": 35.0824,\n    \"lng\": 137.1563,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Aichi\",\n    \"capital\": null,\n    \"population\": 422106.0,\n    \"id\": 1392498272\n  },\n  {\n    \"city\": \"Honchō\",\n    \"city_ascii\": \"Honcho\",\n    \"lat\": 35.6946,\n    \"lng\": 139.9826,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Chiba\",\n    \"capital\": null,\n    \"population\": 641499.0,\n    \"id\": 1392505502\n  },\n  {\n    \"city\": \"Utsunomiya\",\n    \"city_ascii\": \"Utsunomiya\",\n    \"lat\": 36.5551,\n    \"lng\": 139.8826,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tochigi\",\n    \"capital\": \"admin\",\n    \"population\": 518197.0,\n    \"id\": 1392506125\n  },\n  {\n    \"city\": \"Nara\",\n    \"city_ascii\": \"Nara\",\n    \"lat\": 34.6844,\n    \"lng\": 135.805,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Nara\",\n    \"capital\": \"admin\",\n    \"population\": 352377.0,\n    \"id\": 1392520831\n  },\n  {\n    \"city\": \"Shinjuku\",\n    \"city_ascii\": \"Shinjuku\",\n    \"lat\": 35.6939,\n    \"lng\": 139.7034,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 349385.0,\n    \"id\": 1392536374\n  },\n  {\n    \"city\": \"Fukuyama\",\n    \"city_ascii\": \"Fukuyama\",\n    \"lat\": 34.4833,\n    \"lng\": 133.3667,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Hiroshima\",\n    \"capital\": null,\n    \"population\": 459576.0,\n    \"id\": 1392551602\n  },\n  {\n    \"city\": \"Fukuoka\",\n    \"city_ascii\": \"Fukuoka\",\n    \"lat\": 33.5833,\n    \"lng\": 130.4,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Fukuoka\",\n    \"capital\": \"admin\",\n    \"population\": 2286000.0,\n    \"id\": 1392576294\n  },\n  {\n    \"city\": \"Nagano\",\n    \"city_ascii\": \"Nagano\",\n    \"lat\": 36.6486,\n    \"lng\": 138.1947,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Nagano\",\n    \"capital\": \"admin\",\n    \"population\": 367184.0,\n    \"id\": 1392603439\n  },\n  {\n    \"city\": \"Koshigaya\",\n    \"city_ascii\": \"Koshigaya\",\n    \"lat\": 35.8911,\n    \"lng\": 139.7909,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Saitama\",\n    \"capital\": null,\n    \"population\": 346768.0,\n    \"id\": 1392606124\n  },\n  {\n    \"city\": \"Kyōto\",\n    \"city_ascii\": \"Kyoto\",\n    \"lat\": 35.0117,\n    \"lng\": 135.7683,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Kyōto\",\n    \"capital\": \"admin\",\n    \"population\": 1464890.0,\n    \"id\": 1392622735\n  },\n  {\n    \"city\": \"Fujisawa\",\n    \"city_ascii\": \"Fujisawa\",\n    \"lat\": 35.35,\n    \"lng\": 139.4667,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Kanagawa\",\n    \"capital\": null,\n    \"population\": 436744.0,\n    \"id\": 1392640771\n  },\n  {\n    \"city\": \"Matsudo\",\n    \"city_ascii\": \"Matsudo\",\n    \"lat\": 35.7876,\n    \"lng\": 139.9032,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Chiba\",\n    \"capital\": null,\n    \"population\": 497514.0,\n    \"id\": 1392642525\n  },\n  {\n    \"city\": \"Kanazawa\",\n    \"city_ascii\": \"Kanazawa\",\n    \"lat\": 36.5611,\n    \"lng\": 136.6564,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Ishikawa\",\n    \"capital\": \"admin\",\n    \"population\": 462479.0,\n    \"id\": 1392684679\n  },\n  {\n    \"city\": \"Tokyo\",\n    \"city_ascii\": \"Tokyo\",\n    \"lat\": 35.6897,\n    \"lng\": 139.6922,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": \"primary\",\n    \"population\": 37732000.0,\n    \"id\": 1392685764\n  },\n  {\n    \"city\": \"Machida\",\n    \"city_ascii\": \"Machida\",\n    \"lat\": 35.7106,\n    \"lng\": 139.4386,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 434414.0,\n    \"id\": 1392788615\n  },\n  {\n    \"city\": \"Setagaya\",\n    \"city_ascii\": \"Setagaya\",\n    \"lat\": 35.6466,\n    \"lng\": 139.6532,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 940509.0,\n    \"id\": 1392792380\n  },\n  {\n    \"city\": \"Kawagoe\",\n    \"city_ascii\": \"Kawagoe\",\n    \"lat\": 35.9251,\n    \"lng\": 139.4858,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Saitama\",\n    \"capital\": null,\n    \"population\": 354598.0,\n    \"id\": 1392825080\n  },\n  {\n    \"city\": \"Itabashi\",\n    \"city_ascii\": \"Itabashi\",\n    \"lat\": 35.7512,\n    \"lng\": 139.7093,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 581337.0,\n    \"id\": 1392836404\n  },\n  {\n    \"city\": \"Okazaki\",\n    \"city_ascii\": \"Okazaki\",\n    \"lat\": 34.9543,\n    \"lng\": 137.1744,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Aichi\",\n    \"capital\": null,\n    \"population\": 385376.0,\n    \"id\": 1392862345\n  },\n  {\n    \"city\": \"Nakano\",\n    \"city_ascii\": \"Nakano\",\n    \"lat\": 35.7073,\n    \"lng\": 139.6637,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Tōkyō\",\n    \"capital\": null,\n    \"population\": 341014.0,\n    \"id\": 1392891845\n  },\n  {\n    \"city\": \"Wakayama\",\n    \"city_ascii\": \"Wakayama\",\n    \"lat\": 34.2333,\n    \"lng\": 135.1667,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Wakayama\",\n    \"capital\": \"admin\",\n    \"population\": 353299.0,\n    \"id\": 1392907296\n  },\n  {\n    \"city\": \"Niigata\",\n    \"city_ascii\": \"Niigata\",\n    \"lat\": 37.9161,\n    \"lng\": 139.0364,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Niigata\",\n    \"capital\": \"admin\",\n    \"population\": 790646.0,\n    \"id\": 1392913753\n  },\n  {\n    \"city\": \"Minamisuita\",\n    \"city_ascii\": \"Minamisuita\",\n    \"lat\": 34.7594,\n    \"lng\": 135.5169,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Ōsaka\",\n    \"capital\": null,\n    \"population\": 384953.0,\n    \"id\": 1392948850\n  },\n  {\n    \"city\": \"Okayama\",\n    \"city_ascii\": \"Okayama\",\n    \"lat\": 34.65,\n    \"lng\": 133.9167,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Okayama\",\n    \"capital\": \"admin\",\n    \"population\": 720043.0,\n    \"id\": 1392954750\n  },\n  {\n    \"city\": \"Sagamihara\",\n    \"city_ascii\": \"Sagamihara\",\n    \"lat\": 35.5667,\n    \"lng\": 139.3667,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Kanagawa\",\n    \"capital\": null,\n    \"population\": 722973.0,\n    \"id\": 1392967248\n  },\n  {\n    \"city\": \"Kawaguchi\",\n    \"city_ascii\": \"Kawaguchi\",\n    \"lat\": 35.8077,\n    \"lng\": 139.7241,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Saitama\",\n    \"capital\": null,\n    \"population\": 593353.0,\n    \"id\": 1392975133\n  },\n  {\n    \"city\": \"Kōbe\",\n    \"city_ascii\": \"Kobe\",\n    \"lat\": 34.69,\n    \"lng\": 135.1956,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Hyōgo\",\n    \"capital\": \"admin\",\n    \"population\": 1521707.0,\n    \"id\": 1392978082\n  },\n  {\n    \"city\": \"Hirakata\",\n    \"city_ascii\": \"Hirakata\",\n    \"lat\": 34.8167,\n    \"lng\": 135.65,\n    \"country\": \"Japan\",\n    \"iso2\": \"JP\",\n    \"iso3\": \"JPN\",\n    \"admin_name\": \"Ōsaka\",\n    \"capital\": null,\n    \"population\": 396694.0,\n    \"id\": 1392999987\n  },\n  {\n    \"city\": \"Qaraghandy\",\n    \"city_ascii\": \"Qaraghandy\",\n    \"lat\": 49.8028,\n    \"lng\": 73.1056,\n    \"country\": \"Kazakhstan\",\n    \"iso2\": \"KZ\",\n    \"iso3\": \"KAZ\",\n    \"admin_name\": null,\n    \"capital\": \"admin\",\n    \"population\": 497777.0,\n    \"id\": 1398274508\n  },\n  {\n    \"city\": \"Almaty\",\n    \"city_ascii\": \"Almaty\",\n    \"lat\": 43.2775,\n    \"lng\": 76.8958,\n    \"country\": \"Kazakhstan\",\n    \"iso2\": \"KZ\",\n    \"iso3\": \"KAZ\",\n    \"admin_name\": null,\n    \"capital\": \"admin\",\n    \"population\": 1916822.0,\n    \"id\": 1398351701\n  },\n  {\n    \"city\": \"Öskemen\",\n    \"city_ascii\": \"Oskemen\",\n    \"lat\": 49.9833,\n    \"lng\": 82.6167,\n    \"country\": \"Kazakhstan\",\n    \"iso2\": \"KZ\",\n    \"iso3\": \"KAZ\",\n    \"admin_name\": null,\n    \"capital\": \"admin\",\n    \"population\": 346127.0,\n    \"id\": 1398371414\n  },\n  {\n    \"city\": \"Semey\",\n    \"city_ascii\": \"Semey\",\n    \"lat\": 50.4333,\n    \"lng\": 80.2667,\n    \"country\": \"Kazakhstan\",\n    \"iso2\": \"KZ\",\n    \"iso3\": \"KAZ\",\n    \"admin_name\": null,\n    \"capital\": \"admin\",\n    \"population\": 350201.0,\n    \"id\": 1398405657\n  },\n  {\n    \"city\": \"Nur-Sultan\",\n    \"city_ascii\": \"Nur-Sultan\",\n    \"lat\": 51.1472,\n    \"lng\": 71.4222,\n    \"country\": \"Kazakhstan\",\n    \"iso2\": \"KZ\",\n    \"iso3\": \"KAZ\",\n    \"admin_name\": null,\n    \"capital\": \"primary\",\n    \"population\": 1078362.0,\n    \"id\": 1398516045\n  },\n  {\n    \"city\": \"Aqtöbe\",\n    \"city_ascii\": \"Aqtobe\",\n    \"lat\": 50.2836,\n    \"lng\": 57.2297,\n    \"country\": \"Kazakhstan\",\n    \"iso2\": \"KZ\",\n    \"iso3\": \"KAZ\",\n    \"admin_name\": null,\n    \"capital\": \"admin\",\n    \"population\": 387807.0,\n    \"id\": 1398602716\n  },\n  {\n    \"city\": \"Taraz\",\n    \"city_ascii\": \"Taraz\",\n    \"lat\": 42.9,\n    \"lng\": 71.3667,\n    \"country\": \"Kazakhstan\",\n    \"iso2\": \"KZ\",\n    \"iso3\": \"KAZ\",\n    \"admin_name\": null,\n    \"capital\": \"admin\",\n    \"population\": 357795.0,\n    \"id\": 1398626276\n  },\n  {\n    \"city\": \"Pavlodar\",\n    \"city_ascii\": \"Pavlodar\",\n    \"lat\": 52.3,\n    \"lng\": 76.95,\n    \"country\": \"Kazakhstan\",\n    \"iso2\": \"KZ\",\n    \"iso3\": \"KAZ\",\n    \"admin_name\": null,\n    \"capital\": \"admin\",\n    \"population\": 353930.0,\n    \"id\": 1398790087\n  },\n  {\n    \"city\": \"Shymkent\",\n    \"city_ascii\": \"Shymkent\",\n    \"lat\": 42.3167,\n    \"lng\": 69.5958,\n    \"country\": \"Kazakhstan\",\n    \"iso2\": \"KZ\",\n    \"iso3\": \"KAZ\",\n    \"admin_name\": null,\n    \"capital\": \"admin\",\n    \"population\": 1028673.0,\n    \"id\": 1398791401\n  },\n  {\n    \"city\": \"Al Mafraq\",\n    \"city_ascii\": \"Al Mafraq\",\n    \"lat\": 32.3399,\n    \"lng\": 36.2052,\n    \"country\": \"Jordan\",\n    \"iso2\": \"JO\",\n    \"iso3\": \"JOR\",\n    \"admin_name\": \"Al Mafraq\",\n    \"capital\": \"admin\",\n    \"population\": 580000.0,\n    \"id\": 1400040712\n  },\n  {\n    \"city\": \"Az Zarqā’\",\n    \"city_ascii\": \"Az Zarqa'\",\n    \"lat\": 32.0833,\n    \"lng\": 36.1,\n    \"country\": \"Jordan\",\n    \"iso2\": \"JO\",\n    \"iso3\": \"JOR\",\n    \"admin_name\": \"Az Zarqā’\",\n    \"capital\": \"admin\",\n    \"population\": 481300.0,\n    \"id\": 1400161837\n  },\n  {\n    \"city\": \"Irbid\",\n    \"city_ascii\": \"Irbid\",\n    \"lat\": 32.55,\n    \"lng\": 35.85,\n    \"country\": \"Jordan\",\n    \"iso2\": \"JO\",\n    \"iso3\": \"JOR\",\n    \"admin_name\": \"Irbid\",\n    \"capital\": \"admin\",\n    \"population\": 569068.0,\n    \"id\": 1400221568\n  },\n  {\n    \"city\": \"Amman\",\n    \"city_ascii\": \"Amman\",\n    \"lat\": 31.9497,\n    \"lng\": 35.9328,\n    \"country\": \"Jordan\",\n    \"iso2\": \"JO\",\n    \"iso3\": \"JOR\",\n    \"admin_name\": \"Al ‘Āşimah\",\n    \"capital\": \"primary\",\n    \"population\": 4007526.0,\n    \"id\": 1400522593\n  },\n  {\n    \"city\": \"Nairobi\",\n    \"city_ascii\": \"Nairobi\",\n    \"lat\": -1.2864,\n    \"lng\": 36.8172,\n    \"country\": \"Kenya\",\n    \"iso2\": \"KE\",\n    \"iso3\": \"KEN\",\n    \"admin_name\": \"Nairobi City\",\n    \"capital\": \"primary\",\n    \"population\": 5545000.0,\n    \"id\": 1404000661\n  },\n  {\n    \"city\": \"Kisumu\",\n    \"city_ascii\": \"Kisumu\",\n    \"lat\": -0.0833,\n    \"lng\": 34.7667,\n    \"country\": \"Kenya\",\n    \"iso2\": \"KE\",\n    \"iso3\": \"KEN\",\n    \"admin_name\": \"Kisumu\",\n    \"capital\": \"admin\",\n    \"population\": 409928.0,\n    \"id\": 1404511920\n  },\n  {\n    \"city\": \"Mombasa\",\n    \"city_ascii\": \"Mombasa\",\n    \"lat\": -4.05,\n    \"lng\": 39.6667,\n    \"country\": \"Kenya\",\n    \"iso2\": \"KE\",\n    \"iso3\": \"KEN\",\n    \"admin_name\": \"Mombasa\",\n    \"capital\": \"admin\",\n    \"population\": 1208333.0,\n    \"id\": 1404512373\n  },\n  {\n    \"city\": \"Meru\",\n    \"city_ascii\": \"Meru\",\n    \"lat\": 0.05,\n    \"lng\": 37.65,\n    \"country\": \"Kenya\",\n    \"iso2\": \"KE\",\n    \"iso3\": \"KEN\",\n    \"admin_name\": \"Meru\",\n    \"capital\": \"admin\",\n    \"population\": 1833000.0,\n    \"id\": 1404588252\n  },\n  {\n    \"city\": \"Nampo\",\n    \"city_ascii\": \"Nampo\",\n    \"lat\": 38.7333,\n    \"lng\": 125.4,\n    \"country\": \"North Korea\",\n    \"iso2\": \"KP\",\n    \"iso3\": \"PRK\",\n    \"admin_name\": \"Namp’o\",\n    \"capital\": null,\n    \"population\": 703317.0,\n    \"id\": 1408358410\n  },\n  {\n    \"city\": \"Hamhŭng\",\n    \"city_ascii\": \"Hamhung\",\n    \"lat\": 39.9167,\n    \"lng\": 127.5333,\n    \"country\": \"North Korea\",\n    \"iso2\": \"KP\",\n    \"iso3\": \"PRK\",\n    \"admin_name\": \"Hamnam\",\n    \"capital\": \"admin\",\n    \"population\": 768551.0,\n    \"id\": 1408482040\n  },\n  {\n    \"city\": \"Ch’ŏngjin\",\n    \"city_ascii\": \"Ch'ongjin\",\n    \"lat\": 41.7833,\n    \"lng\": 129.7667,\n    \"country\": \"North Korea\",\n    \"iso2\": \"KP\",\n    \"iso3\": \"PRK\",\n    \"admin_name\": \"Hambuk\",\n    \"capital\": \"admin\",\n    \"population\": 667929.0,\n    \"id\": 1408498177\n  },\n  {\n    \"city\": \"Sunch’ŏn\",\n    \"city_ascii\": \"Sunch'on\",\n    \"lat\": 39.4167,\n    \"lng\": 125.9333,\n    \"country\": \"North Korea\",\n    \"iso2\": \"KP\",\n    \"iso3\": \"PRK\",\n    \"admin_name\": \"P’yŏngnam\",\n    \"capital\": null,\n    \"population\": 437000.0,\n    \"id\": 1408510801\n  },\n  {\n    \"city\": \"Wŏnsan\",\n    \"city_ascii\": \"Wonsan\",\n    \"lat\": 39.1475,\n    \"lng\": 127.4461,\n    \"country\": \"North Korea\",\n    \"iso2\": \"KP\",\n    \"iso3\": \"PRK\",\n    \"admin_name\": \"Kangwŏn\",\n    \"capital\": \"admin\",\n    \"population\": 363127.0,\n    \"id\": 1408692125\n  },\n  {\n    \"city\": \"Pyongyang\",\n    \"city_ascii\": \"Pyongyang\",\n    \"lat\": 39.0194,\n    \"lng\": 125.7381,\n    \"country\": \"North Korea\",\n    \"iso2\": \"KP\",\n    \"iso3\": \"PRK\",\n    \"admin_name\": \"P’yŏngyang\",\n    \"capital\": \"primary\",\n    \"population\": 2863000.0,\n    \"id\": 1408738594\n  },\n  {\n    \"city\": \"Sinŭiju\",\n    \"city_ascii\": \"Sinuiju\",\n    \"lat\": 40.1,\n    \"lng\": 124.4,\n    \"country\": \"North Korea\",\n    \"iso2\": \"KP\",\n    \"iso3\": \"PRK\",\n    \"admin_name\": \"P’yŏngbuk\",\n    \"capital\": \"admin\",\n    \"population\": 352000.0,\n    \"id\": 1408740449\n  },\n  {\n    \"city\": \"Tanch’ŏn\",\n    \"city_ascii\": \"Tanch'on\",\n    \"lat\": 40.458,\n    \"lng\": 128.911,\n    \"country\": \"North Korea\",\n    \"iso2\": \"KP\",\n    \"iso3\": \"PRK\",\n    \"admin_name\": \"Hamnam\",\n    \"capital\": null,\n    \"population\": 345876.0,\n    \"id\": 1408940912\n  },\n  {\n    \"city\": \"Gwangju\",\n    \"city_ascii\": \"Gwangju\",\n    \"lat\": 35.1653,\n    \"lng\": 126.8486,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gwangju\",\n    \"capital\": \"admin\",\n    \"population\": 1490092.0,\n    \"id\": 1410000087\n  },\n  {\n    \"city\": \"Yeosu\",\n    \"city_ascii\": \"Yeosu\",\n    \"lat\": 34.7333,\n    \"lng\": 127.7333,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Jeonnam\",\n    \"capital\": \"minor\",\n    \"population\": 341994.0,\n    \"id\": 1410002025\n  },\n  {\n    \"city\": \"Ch’ŏnan\",\n    \"city_ascii\": \"Ch'onan\",\n    \"lat\": 36.8167,\n    \"lng\": 127.1667,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Chungnam\",\n    \"capital\": null,\n    \"population\": 651661.0,\n    \"id\": 1410020455\n  },\n  {\n    \"city\": \"Hwasu-dong\",\n    \"city_ascii\": \"Hwasu-dong\",\n    \"lat\": 37.1997,\n    \"lng\": 126.8314,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": null,\n    \"population\": 655350.0,\n    \"id\": 1410037247\n  },\n  {\n    \"city\": \"Daegu\",\n    \"city_ascii\": \"Daegu\",\n    \"lat\": 35.8717,\n    \"lng\": 128.6017,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Daegu\",\n    \"capital\": \"admin\",\n    \"population\": 2461002.0,\n    \"id\": 1410095252\n  },\n  {\n    \"city\": \"Ulsan\",\n    \"city_ascii\": \"Ulsan\",\n    \"lat\": 35.55,\n    \"lng\": 129.3167,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Ulsan\",\n    \"capital\": \"admin\",\n    \"population\": 1166033.0,\n    \"id\": 1410134602\n  },\n  {\n    \"city\": \"Incheon\",\n    \"city_ascii\": \"Incheon\",\n    \"lat\": 37.4833,\n    \"lng\": 126.6333,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Incheon\",\n    \"capital\": \"admin\",\n    \"population\": 2936117.0,\n    \"id\": 1410160313\n  },\n  {\n    \"city\": \"Tongjin\",\n    \"city_ascii\": \"Tongjin\",\n    \"lat\": 37.2333,\n    \"lng\": 127.2,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": null,\n    \"population\": 1076369.0,\n    \"id\": 1410160862\n  },\n  {\n    \"city\": \"Yanggok\",\n    \"city_ascii\": \"Yanggok\",\n    \"lat\": 37.6333,\n    \"lng\": 127.2167,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": null,\n    \"population\": 713321.0,\n    \"id\": 1410188674\n  },\n  {\n    \"city\": \"Sihŭng\",\n    \"city_ascii\": \"Sihung\",\n    \"lat\": 37.3799,\n    \"lng\": 126.8029,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": null,\n    \"population\": 425184.0,\n    \"id\": 1410313432\n  },\n  {\n    \"city\": \"Jeju\",\n    \"city_ascii\": \"Jeju\",\n    \"lat\": 33.5097,\n    \"lng\": 126.5219,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Jeju\",\n    \"capital\": \"admin\",\n    \"population\": 435413.0,\n    \"id\": 1410364424\n  },\n  {\n    \"city\": \"Paju\",\n    \"city_ascii\": \"Paju\",\n    \"lat\": 37.8667,\n    \"lng\": 126.8,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": \"minor\",\n    \"population\": 415345.0,\n    \"id\": 1410365324\n  },\n  {\n    \"city\": \"Masan\",\n    \"city_ascii\": \"Masan\",\n    \"lat\": 35.1833,\n    \"lng\": 128.55,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeongnam\",\n    \"capital\": null,\n    \"population\": 429612.0,\n    \"id\": 1410394650\n  },\n  {\n    \"city\": \"Bucheon\",\n    \"city_ascii\": \"Bucheon\",\n    \"lat\": 37.5,\n    \"lng\": 126.7833,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": \"minor\",\n    \"population\": 867678.0,\n    \"id\": 1410428222\n  },\n  {\n    \"city\": \"Jeonju\",\n    \"city_ascii\": \"Jeonju\",\n    \"lat\": 35.8167,\n    \"lng\": 127.15,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Jeonbuk\",\n    \"capital\": \"admin\",\n    \"population\": 631532.0,\n    \"id\": 1410494847\n  },\n  {\n    \"city\": \"Goyang\",\n    \"city_ascii\": \"Goyang\",\n    \"lat\": 37.65,\n    \"lng\": 126.8,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": \"minor\",\n    \"population\": 1061929.0,\n    \"id\": 1410511255\n  },\n  {\n    \"city\": \"Anyang\",\n    \"city_ascii\": \"Anyang\",\n    \"lat\": 37.3833,\n    \"lng\": 126.9333,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": null,\n    \"population\": 573296.0,\n    \"id\": 1410581095\n  },\n  {\n    \"city\": \"Ansan\",\n    \"city_ascii\": \"Ansan\",\n    \"lat\": 37.3167,\n    \"lng\": 126.8333,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": null,\n    \"population\": 652800.0,\n    \"id\": 1410585171\n  },\n  {\n    \"city\": \"Changwon\",\n    \"city_ascii\": \"Changwon\",\n    \"lat\": 35.2708,\n    \"lng\": 128.6631,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeongnam\",\n    \"capital\": \"admin\",\n    \"population\": 1046054.0,\n    \"id\": 1410592618\n  },\n  {\n    \"city\": \"Busan\",\n    \"city_ascii\": \"Busan\",\n    \"lat\": 35.18,\n    \"lng\": 129.075,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Busan\",\n    \"capital\": \"admin\",\n    \"population\": 3453198.0,\n    \"id\": 1410601465\n  },\n  {\n    \"city\": \"Sŏngnam\",\n    \"city_ascii\": \"Songnam\",\n    \"lat\": 37.4333,\n    \"lng\": 127.15,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": null,\n    \"population\": 948757.0,\n    \"id\": 1410622472\n  },\n  {\n    \"city\": \"Kumi\",\n    \"city_ascii\": \"Kumi\",\n    \"lat\": 36.1195,\n    \"lng\": 128.3444,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeongbuk\",\n    \"capital\": null,\n    \"population\": 407880.0,\n    \"id\": 1410638233\n  },\n  {\n    \"city\": \"Pyeongtaek\",\n    \"city_ascii\": \"Pyeongtaek\",\n    \"lat\": 36.9922,\n    \"lng\": 127.1128,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": null,\n    \"population\": 457873.0,\n    \"id\": 1410641095\n  },\n  {\n    \"city\": \"Suwon\",\n    \"city_ascii\": \"Suwon\",\n    \"lat\": 37.2667,\n    \"lng\": 127.0167,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": \"admin\",\n    \"population\": 1234300.0,\n    \"id\": 1410679777\n  },\n  {\n    \"city\": \"Gimpo\",\n    \"city_ascii\": \"Gimpo\",\n    \"lat\": 37.7,\n    \"lng\": 126.6,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": \"minor\",\n    \"population\": 352683.0,\n    \"id\": 1410797548\n  },\n  {\n    \"city\": \"Kimhae\",\n    \"city_ascii\": \"Kimhae\",\n    \"lat\": 35.2342,\n    \"lng\": 128.8811,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeongnam\",\n    \"capital\": null,\n    \"population\": 550758.0,\n    \"id\": 1410836094\n  },\n  {\n    \"city\": \"Seoul\",\n    \"city_ascii\": \"Seoul\",\n    \"lat\": 37.56,\n    \"lng\": 126.99,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Seoul\",\n    \"capital\": \"primary\",\n    \"population\": 23016000.0,\n    \"id\": 1410836482\n  },\n  {\n    \"city\": \"Uijeongbu\",\n    \"city_ascii\": \"Uijeongbu\",\n    \"lat\": 37.7486,\n    \"lng\": 127.0389,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeonggi\",\n    \"capital\": null,\n    \"population\": 421579.0,\n    \"id\": 1410888678\n  },\n  {\n    \"city\": \"Cheongju\",\n    \"city_ascii\": \"Cheongju\",\n    \"lat\": 36.6333,\n    \"lng\": 127.4833,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Chungbuk\",\n    \"capital\": \"admin\",\n    \"population\": 833276.0,\n    \"id\": 1410964361\n  },\n  {\n    \"city\": \"Pohang\",\n    \"city_ascii\": \"Pohang\",\n    \"lat\": 36.0322,\n    \"lng\": 129.365,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Gyeongbuk\",\n    \"capital\": \"minor\",\n    \"population\": 520305.0,\n    \"id\": 1410983252\n  },\n  {\n    \"city\": \"Daejeon\",\n    \"city_ascii\": \"Daejeon\",\n    \"lat\": 36.351,\n    \"lng\": 127.385,\n    \"country\": \"South Korea\",\n    \"iso2\": \"KR\",\n    \"iso3\": \"KOR\",\n    \"admin_name\": \"Daejeon\",\n    \"capital\": \"admin\",\n    \"population\": 1475221.0,\n    \"id\": 1410993875\n  },\n  {\n    \"city\": \"Kuwait City\",\n    \"city_ascii\": \"Kuwait City\",\n    \"lat\": 29.3697,\n    \"lng\": 47.9783,\n    \"country\": \"Kuwait\",\n    \"iso2\": \"KW\",\n    \"iso3\": \"KWT\",\n    \"admin_name\": \"Al ‘Āşimah\",\n    \"capital\": \"primary\",\n    \"population\": 3000000.0,\n    \"id\": 1414102075\n  },\n  {\n    \"city\": \"Al Jahrā’\",\n    \"city_ascii\": \"Al Jahra'\",\n    \"lat\": 29.35,\n    \"lng\": 47.6833,\n    \"country\": \"Kuwait\",\n    \"iso2\": \"KW\",\n    \"iso3\": \"KWT\",\n    \"admin_name\": \"Al Jahrā’\",\n    \"capital\": null,\n    \"population\": 393432.0,\n    \"id\": 1414182001\n  },\n  {\n    \"city\": \"Bishkek\",\n    \"city_ascii\": \"Bishkek\",\n    \"lat\": 42.8747,\n    \"lng\": 74.6122,\n    \"country\": \"Kyrgyzstan\",\n    \"iso2\": \"KG\",\n    \"iso3\": \"KGZ\",\n    \"admin_name\": \"Bishkek\",\n    \"capital\": \"primary\",\n    \"population\": 1074075.0,\n    \"id\": 1417191971\n  },\n  {\n    \"city\": \"Vientiane\",\n    \"city_ascii\": \"Vientiane\",\n    \"lat\": 17.9667,\n    \"lng\": 102.6,\n    \"country\": \"Laos\",\n    \"iso2\": \"LA\",\n    \"iso3\": \"LAO\",\n    \"admin_name\": \"Viangchan\",\n    \"capital\": \"primary\",\n    \"population\": 948487.0,\n    \"id\": 1418732714\n  },\n  {\n    \"city\": \"Beirut\",\n    \"city_ascii\": \"Beirut\",\n    \"lat\": 33.8869,\n    \"lng\": 35.5131,\n    \"country\": \"Lebanon\",\n    \"iso2\": \"LB\",\n    \"iso3\": \"LBN\",\n    \"admin_name\": \"Beyrouth\",\n    \"capital\": \"primary\",\n    \"population\": 361366.0,\n    \"id\": 1422847713\n  },\n  {\n    \"city\": \"Tripoli\",\n    \"city_ascii\": \"Tripoli\",\n    \"lat\": 34.4367,\n    \"lng\": 35.8344,\n    \"country\": \"Lebanon\",\n    \"iso2\": \"LB\",\n    \"iso3\": \"LBN\",\n    \"admin_name\": \"Liban-Nord\",\n    \"capital\": \"admin\",\n    \"population\": 530000.0,\n    \"id\": 1422886065\n  },\n  {\n    \"city\": \"Maseru\",\n    \"city_ascii\": \"Maseru\",\n    \"lat\": -29.31,\n    \"lng\": 27.48,\n    \"country\": \"Lesotho\",\n    \"iso2\": \"LS\",\n    \"iso3\": \"LSO\",\n    \"admin_name\": \"Maseru\",\n    \"capital\": \"primary\",\n    \"population\": 519186.0,\n    \"id\": 1426977668\n  },\n  {\n    \"city\": \"Riga\",\n    \"city_ascii\": \"Riga\",\n    \"lat\": 56.9489,\n    \"lng\": 24.1064,\n    \"country\": \"Latvia\",\n    \"iso2\": \"LV\",\n    \"iso3\": \"LVA\",\n    \"admin_name\": \"Rīga\",\n    \"capital\": \"primary\",\n    \"population\": 920643.0,\n    \"id\": 1428586192\n  },\n  {\n    \"city\": \"Monrovia\",\n    \"city_ascii\": \"Monrovia\",\n    \"lat\": 6.3133,\n    \"lng\": -10.8014,\n    \"country\": \"Liberia\",\n    \"iso2\": \"LR\",\n    \"iso3\": \"LBR\",\n    \"admin_name\": \"Montserrado\",\n    \"capital\": \"primary\",\n    \"population\": 1021762.0,\n    \"id\": 1430477826\n  },\n  {\n    \"city\": \"Tripoli\",\n    \"city_ascii\": \"Tripoli\",\n    \"lat\": 32.8872,\n    \"lng\": 13.1914,\n    \"country\": \"Libya\",\n    \"iso2\": \"LY\",\n    \"iso3\": \"LBY\",\n    \"admin_name\": \"Ţarābulus\",\n    \"capital\": \"primary\",\n    \"population\": 1293016.0,\n    \"id\": 1434201852\n  },\n  {\n    \"city\": \"Ajdābiyā\",\n    \"city_ascii\": \"Ajdabiya\",\n    \"lat\": 30.7556,\n    \"lng\": 20.2253,\n    \"country\": \"Libya\",\n    \"iso2\": \"LY\",\n    \"iso3\": \"LBY\",\n    \"admin_name\": \"Al Wāḩāt\",\n    \"capital\": \"admin\",\n    \"population\": 416000.0,\n    \"id\": 1434401280\n  },\n  {\n    \"city\": \"Benghazi\",\n    \"city_ascii\": \"Benghazi\",\n    \"lat\": 32.1167,\n    \"lng\": 20.0667,\n    \"country\": \"Libya\",\n    \"iso2\": \"LY\",\n    \"iso3\": \"LBY\",\n    \"admin_name\": \"Banghāzī\",\n    \"capital\": \"admin\",\n    \"population\": 631555.0,\n    \"id\": 1434915572\n  },\n  {\n    \"city\": \"Kaunas\",\n    \"city_ascii\": \"Kaunas\",\n    \"lat\": 54.8972,\n    \"lng\": 23.8861,\n    \"country\": \"Lithuania\",\n    \"iso2\": \"LT\",\n    \"iso3\": \"LTU\",\n    \"admin_name\": \"Kauno Miestas\",\n    \"capital\": \"admin\",\n    \"population\": 381007.0,\n    \"id\": 1440302852\n  },\n  {\n    \"city\": \"Vilnius\",\n    \"city_ascii\": \"Vilnius\",\n    \"lat\": 54.6872,\n    \"lng\": 25.28,\n    \"country\": \"Lithuania\",\n    \"iso2\": \"LT\",\n    \"iso3\": \"LTU\",\n    \"admin_name\": \"Vilniaus Miestas\",\n    \"capital\": \"primary\",\n    \"population\": 708203.0,\n    \"id\": 1440887149\n  },\n  {\n    \"city\": \"Macau\",\n    \"city_ascii\": \"Macau\",\n    \"lat\": 22.2006,\n    \"lng\": 113.5461,\n    \"country\": \"Macau\",\n    \"iso2\": \"MO\",\n    \"iso3\": \"MAC\",\n    \"admin_name\": null,\n    \"capital\": null,\n    \"population\": 568700.0,\n    \"id\": 1446227359\n  },\n  {\n    \"city\": \"Androtsy\",\n    \"city_ascii\": \"Androtsy\",\n    \"lat\": -24.1,\n    \"lng\": 46.3,\n    \"country\": \"Madagascar\",\n    \"iso2\": \"MG\",\n    \"iso3\": \"MDG\",\n    \"admin_name\": \"Toliara\",\n    \"capital\": null,\n    \"population\": 809313.0,\n    \"id\": 1450017816\n  },\n  {\n    \"city\": \"Betsiboka\",\n    \"city_ascii\": \"Betsiboka\",\n    \"lat\": -16.95,\n    \"lng\": 46.83,\n    \"country\": \"Madagascar\",\n    \"iso2\": \"MG\",\n    \"iso3\": \"MDG\",\n    \"admin_name\": \"Mahajanga\",\n    \"capital\": null,\n    \"population\": 394561.0,\n    \"id\": 1450524066\n  },\n  {\n    \"city\": \"Antananarivo\",\n    \"city_ascii\": \"Antananarivo\",\n    \"lat\": -18.9333,\n    \"lng\": 47.5167,\n    \"country\": \"Madagascar\",\n    \"iso2\": \"MG\",\n    \"iso3\": \"MDG\",\n    \"admin_name\": \"Antananarivo\",\n    \"capital\": \"primary\",\n    \"population\": 2610000.0,\n    \"id\": 1450978461\n  },\n  {\n    \"city\": \"Blantyre\",\n    \"city_ascii\": \"Blantyre\",\n    \"lat\": -15.7861,\n    \"lng\": 35.0058,\n    \"country\": \"Malawi\",\n    \"iso2\": \"MW\",\n    \"iso3\": \"MWI\",\n    \"admin_name\": \"Blantyre\",\n    \"capital\": \"admin\",\n    \"population\": 1895973.0,\n    \"id\": 1454145012\n  },\n  {\n    \"city\": \"Lilongwe\",\n    \"city_ascii\": \"Lilongwe\",\n    \"lat\": -13.9833,\n    \"lng\": 33.7833,\n    \"country\": \"Malawi\",\n    \"iso2\": \"MW\",\n    \"iso3\": \"MWI\",\n    \"admin_name\": \"Lilongwe\",\n    \"capital\": \"primary\",\n    \"population\": 989318.0,\n    \"id\": 1454688499\n  },\n  {\n    \"city\": \"Seremban\",\n    \"city_ascii\": \"Seremban\",\n    \"lat\": 2.7222,\n    \"lng\": 101.9417,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Negeri Sembilan\",\n    \"capital\": \"admin\",\n    \"population\": 419536.0,\n    \"id\": 1458051507\n  },\n  {\n    \"city\": \"Kota Bharu\",\n    \"city_ascii\": \"Kota Bharu\",\n    \"lat\": 6.1333,\n    \"lng\": 102.25,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Kelantan\",\n    \"capital\": \"admin\",\n    \"population\": 491237.0,\n    \"id\": 1458150101\n  },\n  {\n    \"city\": \"Shah Alam\",\n    \"city_ascii\": \"Shah Alam\",\n    \"lat\": 3.0722,\n    \"lng\": 101.5167,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Selangor\",\n    \"capital\": \"admin\",\n    \"population\": 584340.0,\n    \"id\": 1458194263\n  },\n  {\n    \"city\": \"George Town\",\n    \"city_ascii\": \"George Town\",\n    \"lat\": 5.4144,\n    \"lng\": 100.3292,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Pulau Pinang\",\n    \"capital\": \"admin\",\n    \"population\": 794313.0,\n    \"id\": 1458236750\n  },\n  {\n    \"city\": \"Sandakan\",\n    \"city_ascii\": \"Sandakan\",\n    \"lat\": 5.8388,\n    \"lng\": 118.1173,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Sabah\",\n    \"capital\": null,\n    \"population\": 396290.0,\n    \"id\": 1458405180\n  },\n  {\n    \"city\": \"Seberang Jaya\",\n    \"city_ascii\": \"Seberang Jaya\",\n    \"lat\": 5.4,\n    \"lng\": 100.4667,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Pulau Pinang\",\n    \"capital\": null,\n    \"population\": 946092.0,\n    \"id\": 1458417183\n  },\n  {\n    \"city\": \"Ipoh\",\n    \"city_ascii\": \"Ipoh\",\n    \"lat\": 4.5972,\n    \"lng\": 101.075,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Perak\",\n    \"capital\": \"admin\",\n    \"population\": 866772.0,\n    \"id\": 1458423505\n  },\n  {\n    \"city\": \"Kota Kinabalu\",\n    \"city_ascii\": \"Kota Kinabalu\",\n    \"lat\": 5.975,\n    \"lng\": 116.0725,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Sabah\",\n    \"capital\": \"admin\",\n    \"population\": 452058.0,\n    \"id\": 1458441859\n  },\n  {\n    \"city\": \"Melaka\",\n    \"city_ascii\": \"Melaka\",\n    \"lat\": 2.1944,\n    \"lng\": 102.2486,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Melaka\",\n    \"capital\": \"admin\",\n    \"population\": 455300.0,\n    \"id\": 1458467506\n  },\n  {\n    \"city\": \"Butterworth\",\n    \"city_ascii\": \"Butterworth\",\n    \"lat\": 5.3992,\n    \"lng\": 100.3639,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Pulau Pinang\",\n    \"capital\": null,\n    \"population\": 821652.0,\n    \"id\": 1458469233\n  },\n  {\n    \"city\": \"Klang\",\n    \"city_ascii\": \"Klang\",\n    \"lat\": 3.0333,\n    \"lng\": 101.45,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Selangor\",\n    \"capital\": null,\n    \"population\": 878000.0,\n    \"id\": 1458509635\n  },\n  {\n    \"city\": \"Sungai Petani\",\n    \"city_ascii\": \"Sungai Petani\",\n    \"lat\": 5.65,\n    \"lng\": 100.48,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Kedah\",\n    \"capital\": null,\n    \"population\": 358499.0,\n    \"id\": 1458639918\n  },\n  {\n    \"city\": \"Johor Bahru\",\n    \"city_ascii\": \"Johor Bahru\",\n    \"lat\": 1.4556,\n    \"lng\": 103.7611,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Johor\",\n    \"capital\": \"admin\",\n    \"population\": 497097.0,\n    \"id\": 1458747615\n  },\n  {\n    \"city\": \"Kuantan\",\n    \"city_ascii\": \"Kuantan\",\n    \"lat\": 3.8167,\n    \"lng\": 103.3333,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Pahang\",\n    \"capital\": \"admin\",\n    \"population\": 607778.0,\n    \"id\": 1458763489\n  },\n  {\n    \"city\": \"Kuala Lumpur\",\n    \"city_ascii\": \"Kuala Lumpur\",\n    \"lat\": 3.1478,\n    \"lng\": 101.6953,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Kuala Lumpur\",\n    \"capital\": \"primary\",\n    \"population\": 8911000.0,\n    \"id\": 1458988644\n  },\n  {\n    \"city\": \"Petaling Jaya\",\n    \"city_ascii\": \"Petaling Jaya\",\n    \"lat\": 3.0972,\n    \"lng\": 101.6444,\n    \"country\": \"Malaysia\",\n    \"iso2\": \"MY\",\n    \"iso3\": \"MYS\",\n    \"admin_name\": \"Selangor\",\n    \"capital\": null,\n    \"population\": 638516.0,\n    \"id\": 1458989343\n  },\n  {\n    \"city\": \"Balandougou\",\n    \"city_ascii\": \"Balandougou\",\n    \"lat\": 13.3558,\n    \"lng\": -9.5517,\n    \"country\": \"Mali\",\n    \"iso2\": \"ML\",\n    \"iso3\": \"MLI\",\n    \"admin_name\": \"Kayes\",\n    \"capital\": null,\n    \"population\": 1596882.0,\n    \"id\": 1466367944\n  },\n  {\n    \"city\": \"Bamako\",\n    \"city_ascii\": \"Bamako\",\n    \"lat\": 12.6458,\n    \"lng\": -7.9922,\n    \"country\": \"Mali\",\n    \"iso2\": \"ML\",\n    \"iso3\": \"MLI\",\n    \"admin_name\": \"Bamako\",\n    \"capital\": \"primary\",\n    \"population\": 2009109.0,\n    \"id\": 1466965925\n  },\n  {\n    \"city\": \"Valletta\",\n    \"city_ascii\": \"Valletta\",\n    \"lat\": 35.8983,\n    \"lng\": 14.5125,\n    \"country\": \"Malta\",\n    \"iso2\": \"MT\",\n    \"iso3\": \"MLT\",\n    \"admin_name\": \"Valletta\",\n    \"capital\": \"primary\",\n    \"population\": 480134.0,\n    \"id\": 1470574399\n  },\n  {\n    \"city\": \"Nouakchott\",\n    \"city_ascii\": \"Nouakchott\",\n    \"lat\": 18.0858,\n    \"lng\": -15.9785,\n    \"country\": \"Mauritania\",\n    \"iso2\": \"MR\",\n    \"iso3\": \"MRT\",\n    \"admin_name\": \"Nouakchott Ouest\",\n    \"capital\": \"primary\",\n    \"population\": 1077169.0,\n    \"id\": 1478414984\n  },\n  {\n    \"city\": \"Guadalupe\",\n    \"city_ascii\": \"Guadalupe\",\n    \"lat\": 25.6775,\n    \"lng\": -100.2597,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Nuevo León\",\n    \"capital\": \"minor\",\n    \"population\": 691931.0,\n    \"id\": 1484002410\n  },\n  {\n    \"city\": \"Ecatepec\",\n    \"city_ascii\": \"Ecatepec\",\n    \"lat\": 19.6097,\n    \"lng\": -99.06,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"México\",\n    \"capital\": \"minor\",\n    \"population\": 1929926.0,\n    \"id\": 1484003694\n  },\n  {\n    \"city\": \"Cancún\",\n    \"city_ascii\": \"Cancun\",\n    \"lat\": 21.1606,\n    \"lng\": -86.8475,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Quintana Roo\",\n    \"capital\": \"minor\",\n    \"population\": 888797.0,\n    \"id\": 1484010310\n  },\n  {\n    \"city\": \"Hermosillo\",\n    \"city_ascii\": \"Hermosillo\",\n    \"lat\": 29.0989,\n    \"lng\": -110.9542,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Sonora\",\n    \"capital\": \"admin\",\n    \"population\": 855563.0,\n    \"id\": 1484015319\n  },\n  {\n    \"city\": \"Ciudad Nezahualcóyotl\",\n    \"city_ascii\": \"Ciudad Nezahualcoyotl\",\n    \"lat\": 19.4081,\n    \"lng\": -99.0186,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"México\",\n    \"capital\": null,\n    \"population\": 1109363.0,\n    \"id\": 1484016661\n  },\n  {\n    \"city\": \"Tlajomulco de Zúñiga\",\n    \"city_ascii\": \"Tlajomulco de Zuniga\",\n    \"lat\": 20.4736,\n    \"lng\": -103.4431,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Jalisco\",\n    \"capital\": \"minor\",\n    \"population\": 727750.0,\n    \"id\": 1484017493\n  },\n  {\n    \"city\": \"Nezahualcóyotl\",\n    \"city_ascii\": \"Nezahualcoyotl\",\n    \"lat\": 19.4006,\n    \"lng\": -99.0148,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"México\",\n    \"capital\": \"minor\",\n    \"population\": 1077208.0,\n    \"id\": 1484074285\n  },\n  {\n    \"city\": \"Tlaquepaque\",\n    \"city_ascii\": \"Tlaquepaque\",\n    \"lat\": 20.6167,\n    \"lng\": -103.3167,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Jalisco\",\n    \"capital\": \"minor\",\n    \"population\": 664193.0,\n    \"id\": 1484087945\n  },\n  {\n    \"city\": \"Gómez Palacio\",\n    \"city_ascii\": \"Gomez Palacio\",\n    \"lat\": 25.5611,\n    \"lng\": -103.4983,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Durango\",\n    \"capital\": \"minor\",\n    \"population\": 342286.0,\n    \"id\": 1484092318\n  },\n  {\n    \"city\": \"Saltillo\",\n    \"city_ascii\": \"Saltillo\",\n    \"lat\": 25.4231,\n    \"lng\": -100.9919,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Coahuila\",\n    \"capital\": \"admin\",\n    \"population\": 864431.0,\n    \"id\": 1484107245\n  },\n  {\n    \"city\": \"Zapopan\",\n    \"city_ascii\": \"Zapopan\",\n    \"lat\": 20.7167,\n    \"lng\": -103.4,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Jalisco\",\n    \"capital\": \"minor\",\n    \"population\": 1476491.0,\n    \"id\": 1484198680\n  },\n  {\n    \"city\": \"Torreón\",\n    \"city_ascii\": \"Torreon\",\n    \"lat\": 25.5394,\n    \"lng\": -103.4486,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Coahuila\",\n    \"capital\": \"minor\",\n    \"population\": 716672.0,\n    \"id\": 1484215762\n  },\n  {\n    \"city\": \"Mexico City\",\n    \"city_ascii\": \"Mexico City\",\n    \"lat\": 19.4333,\n    \"lng\": -99.1333,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Ciudad de México\",\n    \"capital\": \"primary\",\n    \"population\": 21804000.0,\n    \"id\": 1484247881\n  },\n  {\n    \"city\": \"San Nicolás de los Garza\",\n    \"city_ascii\": \"San Nicolas de los Garza\",\n    \"lat\": 25.75,\n    \"lng\": -100.2833,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Nuevo León\",\n    \"capital\": \"minor\",\n    \"population\": 443273.0,\n    \"id\": 1484264138\n  },\n  {\n    \"city\": \"Xalapa\",\n    \"city_ascii\": \"Xalapa\",\n    \"lat\": 19.54,\n    \"lng\": -96.9275,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Veracruz\",\n    \"capital\": \"admin\",\n    \"population\": 424755.0,\n    \"id\": 1484334948\n  },\n  {\n    \"city\": \"Chihuahua\",\n    \"city_ascii\": \"Chihuahua\",\n    \"lat\": 28.6353,\n    \"lng\": -106.0889,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Chihuahua\",\n    \"capital\": \"admin\",\n    \"population\": 878062.0,\n    \"id\": 1484335603\n  },\n  {\n    \"city\": \"Tecámac\",\n    \"city_ascii\": \"Tecamac\",\n    \"lat\": 19.7131,\n    \"lng\": -98.9683,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"México\",\n    \"capital\": \"minor\",\n    \"population\": 364579.0,\n    \"id\": 1484363321\n  },\n  {\n    \"city\": \"Ciudad López Mateos\",\n    \"city_ascii\": \"Ciudad Lopez Mateos\",\n    \"lat\": 19.55,\n    \"lng\": -99.2833,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"México\",\n    \"capital\": \"minor\",\n    \"population\": 489937.0,\n    \"id\": 1484363879\n  },\n  {\n    \"city\": \"Mérida\",\n    \"city_ascii\": \"Merida\",\n    \"lat\": 20.97,\n    \"lng\": -89.62,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Yucatán\",\n    \"capital\": \"admin\",\n    \"population\": 892363.0,\n    \"id\": 1484396779\n  },\n  {\n    \"city\": \"Puebla\",\n    \"city_ascii\": \"Puebla\",\n    \"lat\": 19.0333,\n    \"lng\": -98.1833,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Puebla\",\n    \"capital\": \"admin\",\n    \"population\": 1576259.0,\n    \"id\": 1484416394\n  },\n  {\n    \"city\": \"Tepic\",\n    \"city_ascii\": \"Tepic\",\n    \"lat\": 21.5083,\n    \"lng\": -104.8931,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Nayarit\",\n    \"capital\": \"admin\",\n    \"population\": 413609.0,\n    \"id\": 1484433877\n  },\n  {\n    \"city\": \"Los Mochis\",\n    \"city_ascii\": \"Los Mochis\",\n    \"lat\": 25.7835,\n    \"lng\": -108.9937,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Sinaloa\",\n    \"capital\": \"minor\",\n    \"population\": 490000.0,\n    \"id\": 1484443585\n  },\n  {\n    \"city\": \"Ixtapaluca\",\n    \"city_ascii\": \"Ixtapaluca\",\n    \"lat\": 19.3186,\n    \"lng\": -98.8822,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"México\",\n    \"capital\": \"minor\",\n    \"population\": 542211.0,\n    \"id\": 1484452937\n  },\n  {\n    \"city\": \"Villahermosa\",\n    \"city_ascii\": \"Villahermosa\",\n    \"lat\": 17.9892,\n    \"lng\": -92.9281,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Tabasco\",\n    \"capital\": \"admin\",\n    \"population\": 353577.0,\n    \"id\": 1484460894\n  },\n  {\n    \"city\": \"Acapulco de Juárez\",\n    \"city_ascii\": \"Acapulco de Juarez\",\n    \"lat\": 16.8636,\n    \"lng\": -99.8825,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Guerrero\",\n    \"capital\": \"minor\",\n    \"population\": 673478.0,\n    \"id\": 1484463183\n  },\n  {\n    \"city\": \"Chimalhuacán\",\n    \"city_ascii\": \"Chimalhuacan\",\n    \"lat\": 19.4167,\n    \"lng\": -98.9,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"México\",\n    \"capital\": \"minor\",\n    \"population\": 614453.0,\n    \"id\": 1484504936\n  },\n  {\n    \"city\": \"Culiacán\",\n    \"city_ascii\": \"Culiacan\",\n    \"lat\": 24.8069,\n    \"lng\": -107.3939,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Sinaloa\",\n    \"capital\": \"admin\",\n    \"population\": 808416.0,\n    \"id\": 1484516810\n  },\n  {\n    \"city\": \"Monterrey\",\n    \"city_ascii\": \"Monterrey\",\n    \"lat\": 25.6667,\n    \"lng\": -100.3,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Nuevo León\",\n    \"capital\": \"admin\",\n    \"population\": 5341171.0,\n    \"id\": 1484559591\n  },\n  {\n    \"city\": \"Tultitlán de Mariano Escobedo\",\n    \"city_ascii\": \"Tultitlan de Mariano Escobedo\",\n    \"lat\": 19.645,\n    \"lng\": -99.1694,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"México\",\n    \"capital\": \"minor\",\n    \"population\": 520557.0,\n    \"id\": 1484562374\n  },\n  {\n    \"city\": \"San Luis Potosí\",\n    \"city_ascii\": \"San Luis Potosi\",\n    \"lat\": 22.1511,\n    \"lng\": -100.9761,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"San Luis Potosí\",\n    \"capital\": \"admin\",\n    \"population\": 772828.0,\n    \"id\": 1484583620\n  },\n  {\n    \"city\": \"Nicolás Romero\",\n    \"city_ascii\": \"Nicolas Romero\",\n    \"lat\": 19.5833,\n    \"lng\": -99.3667,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"México\",\n    \"capital\": \"minor\",\n    \"population\": 366602.0,\n    \"id\": 1484589606\n  },\n  {\n    \"city\": \"Nuevo Laredo\",\n    \"city_ascii\": \"Nuevo Laredo\",\n    \"lat\": 27.4861,\n    \"lng\": -99.5069,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Tamaulipas\",\n    \"capital\": \"minor\",\n    \"population\": 384033.0,\n    \"id\": 1484597234\n  },\n  {\n    \"city\": \"Querétaro\",\n    \"city_ascii\": \"Queretaro\",\n    \"lat\": 20.5875,\n    \"lng\": -100.3928,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Querétaro\",\n    \"capital\": \"admin\",\n    \"population\": 801940.0,\n    \"id\": 1484604775\n  },\n  {\n    \"city\": \"Heroica Matamoros\",\n    \"city_ascii\": \"Heroica Matamoros\",\n    \"lat\": 25.8797,\n    \"lng\": -97.5042,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Tamaulipas\",\n    \"capital\": \"minor\",\n    \"population\": 541979.0,\n    \"id\": 1484614906\n  },\n  {\n    \"city\": \"Irapuato\",\n    \"city_ascii\": \"Irapuato\",\n    \"lat\": 20.6667,\n    \"lng\": -101.35,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Guanajuato\",\n    \"capital\": \"minor\",\n    \"population\": 592953.0,\n    \"id\": 1484625454\n  },\n  {\n    \"city\": \"Aguascalientes\",\n    \"city_ascii\": \"Aguascalientes\",\n    \"lat\": 21.876,\n    \"lng\": -102.296,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Aguascalientes\",\n    \"capital\": \"admin\",\n    \"population\": 934424.0,\n    \"id\": 1484666646\n  },\n  {\n    \"city\": \"Morelia\",\n    \"city_ascii\": \"Morelia\",\n    \"lat\": 19.7683,\n    \"lng\": -101.1894,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Michoacán\",\n    \"capital\": null,\n    \"population\": 962555.0,\n    \"id\": 1484669072\n  },\n  {\n    \"city\": \"Tijuana\",\n    \"city_ascii\": \"Tijuana\",\n    \"lat\": 32.525,\n    \"lng\": -117.0333,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Baja California\",\n    \"capital\": \"minor\",\n    \"population\": 2002000.0,\n    \"id\": 1484708778\n  },\n  {\n    \"city\": \"Ensenada\",\n    \"city_ascii\": \"Ensenada\",\n    \"lat\": 31.8578,\n    \"lng\": -116.6058,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Baja California\",\n    \"capital\": \"minor\",\n    \"population\": 557430.0,\n    \"id\": 1484714297\n  },\n  {\n    \"city\": \"Minatitlán\",\n    \"city_ascii\": \"Minatitlan\",\n    \"lat\": 17.9833,\n    \"lng\": -94.55,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Veracruz\",\n    \"capital\": \"minor\",\n    \"population\": 356020.0,\n    \"id\": 1484735713\n  },\n  {\n    \"city\": \"Reynosa\",\n    \"city_ascii\": \"Reynosa\",\n    \"lat\": 26.0922,\n    \"lng\": -98.2778,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Tamaulipas\",\n    \"capital\": \"minor\",\n    \"population\": 725793.0,\n    \"id\": 1484737671\n  },\n  {\n    \"city\": \"Tonalá\",\n    \"city_ascii\": \"Tonala\",\n    \"lat\": 20.6167,\n    \"lng\": -103.2333,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Jalisco\",\n    \"capital\": \"minor\",\n    \"population\": 569913.0,\n    \"id\": 1484750897\n  },\n  {\n    \"city\": \"Orizaba\",\n    \"city_ascii\": \"Orizaba\",\n    \"lat\": 18.85,\n    \"lng\": -97.1,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Veracruz\",\n    \"capital\": \"minor\",\n    \"population\": 355333.0,\n    \"id\": 1484766767\n  },\n  {\n    \"city\": \"Mexicali\",\n    \"city_ascii\": \"Mexicali\",\n    \"lat\": 32.6633,\n    \"lng\": -115.4678,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Baja California\",\n    \"capital\": \"admin\",\n    \"population\": 1102342.0,\n    \"id\": 1484788702\n  },\n  {\n    \"city\": \"León de los Aldama\",\n    \"city_ascii\": \"Leon de los Aldama\",\n    \"lat\": 21.1167,\n    \"lng\": -101.6833,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Guanajuato\",\n    \"capital\": \"minor\",\n    \"population\": 1579803.0,\n    \"id\": 1484811199\n  },\n  {\n    \"city\": \"Tuxtla\",\n    \"city_ascii\": \"Tuxtla\",\n    \"lat\": 16.7528,\n    \"lng\": -93.1167,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Chiapas\",\n    \"capital\": \"admin\",\n    \"population\": 598710.0,\n    \"id\": 1484832519\n  },\n  {\n    \"city\": \"Juárez\",\n    \"city_ascii\": \"Juarez\",\n    \"lat\": 31.7386,\n    \"lng\": -106.487,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Chihuahua\",\n    \"capital\": \"minor\",\n    \"population\": 1321004.0,\n    \"id\": 1484840083\n  },\n  {\n    \"city\": \"Mazatlán\",\n    \"city_ascii\": \"Mazatlan\",\n    \"lat\": 23.2167,\n    \"lng\": -106.4167,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Sinaloa\",\n    \"capital\": \"minor\",\n    \"population\": 658354.0,\n    \"id\": 1484841466\n  },\n  {\n    \"city\": \"Naucalpan de Juárez\",\n    \"city_ascii\": \"Naucalpan de Juarez\",\n    \"lat\": 19.4753,\n    \"lng\": -99.2378,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"México\",\n    \"capital\": \"minor\",\n    \"population\": 913681.0,\n    \"id\": 1484850125\n  },\n  {\n    \"city\": \"Durango\",\n    \"city_ascii\": \"Durango\",\n    \"lat\": 24.025,\n    \"lng\": -104.6675,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Durango\",\n    \"capital\": \"admin\",\n    \"population\": 654876.0,\n    \"id\": 1484854616\n  },\n  {\n    \"city\": \"Ciudad Apodaca\",\n    \"city_ascii\": \"Ciudad Apodaca\",\n    \"lat\": 25.7817,\n    \"lng\": -100.1886,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Nuevo León\",\n    \"capital\": \"minor\",\n    \"population\": 523370.0,\n    \"id\": 1484855080\n  },\n  {\n    \"city\": \"Tlalnepantla\",\n    \"city_ascii\": \"Tlalnepantla\",\n    \"lat\": 19.5367,\n    \"lng\": -99.1947,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"México\",\n    \"capital\": \"minor\",\n    \"population\": 653410.0,\n    \"id\": 1484861603\n  },\n  {\n    \"city\": \"Guadalajara\",\n    \"city_ascii\": \"Guadalajara\",\n    \"lat\": 20.6767,\n    \"lng\": -103.3475,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Jalisco\",\n    \"capital\": \"admin\",\n    \"population\": 5525000.0,\n    \"id\": 1484950208\n  },\n  {\n    \"city\": \"Celaya\",\n    \"city_ascii\": \"Celaya\",\n    \"lat\": 20.5222,\n    \"lng\": -100.8122,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Guanajuato\",\n    \"capital\": \"minor\",\n    \"population\": 494304.0,\n    \"id\": 1484979555\n  },\n  {\n    \"city\": \"Veracruz\",\n    \"city_ascii\": \"Veracruz\",\n    \"lat\": 19.1903,\n    \"lng\": -96.1533,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Veracruz\",\n    \"capital\": \"minor\",\n    \"population\": 428323.0,\n    \"id\": 1484992153\n  },\n  {\n    \"city\": \"Tapachula\",\n    \"city_ascii\": \"Tapachula\",\n    \"lat\": 14.9,\n    \"lng\": -92.2667,\n    \"country\": \"Mexico\",\n    \"iso2\": \"MX\",\n    \"iso3\": \"MEX\",\n    \"admin_name\": \"Chiapas\",\n    \"capital\": \"minor\",\n    \"population\": 348156.0,\n    \"id\": 1484997178\n  },\n  {\n    \"city\": \"Ulaanbaatar\",\n    \"city_ascii\": \"Ulaanbaatar\",\n    \"lat\": 47.9203,\n    \"lng\": 106.9172,\n    \"country\": \"Mongolia\",\n    \"iso2\": \"MN\",\n    \"iso3\": \"MNG\",\n    \"admin_name\": \"Ulaanbaatar\",\n    \"capital\": \"primary\",\n    \"population\": 1396288.0,\n    \"id\": 1496024767\n  },\n  {\n    \"city\": \"Chisinau\",\n    \"city_ascii\": \"Chisinau\",\n    \"lat\": 47.0228,\n    \"lng\": 28.8353,\n    \"country\": \"Moldova\",\n    \"iso2\": \"MD\",\n    \"iso3\": \"MDA\",\n    \"admin_name\": \"Chişinău\",\n    \"capital\": \"primary\",\n    \"population\": 702300.0,\n    \"id\": 1498011437\n  },\n  {\n    \"city\": \"Rabat\",\n    \"city_ascii\": \"Rabat\",\n    \"lat\": 34.0209,\n    \"lng\": -6.8416,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Rabat-Salé-Kénitra\",\n    \"capital\": \"primary\",\n    \"population\": 572717.0,\n    \"id\": 1504023252\n  },\n  {\n    \"city\": \"Agadir\",\n    \"city_ascii\": \"Agadir\",\n    \"lat\": 30.4333,\n    \"lng\": -9.6,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Souss-Massa\",\n    \"capital\": \"admin\",\n    \"population\": 421844.0,\n    \"id\": 1504116858\n  },\n  {\n    \"city\": \"Marrakech\",\n    \"city_ascii\": \"Marrakech\",\n    \"lat\": 31.63,\n    \"lng\": -8.0089,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Marrakech-Safi\",\n    \"capital\": \"admin\",\n    \"population\": 928850.0,\n    \"id\": 1504172585\n  },\n  {\n    \"city\": \"Casablanca\",\n    \"city_ascii\": \"Casablanca\",\n    \"lat\": 33.5333,\n    \"lng\": -7.5833,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Casablanca-Settat\",\n    \"capital\": \"admin\",\n    \"population\": 4370000.0,\n    \"id\": 1504175315\n  },\n  {\n    \"city\": \"Meknès\",\n    \"city_ascii\": \"Meknes\",\n    \"lat\": 33.895,\n    \"lng\": -5.5547,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Fès-Meknès\",\n    \"capital\": null,\n    \"population\": 520428.0,\n    \"id\": 1504333193\n  },\n  {\n    \"city\": \"Mediouna\",\n    \"city_ascii\": \"Mediouna\",\n    \"lat\": 33.45,\n    \"lng\": -7.51,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Casablanca-Settat\",\n    \"capital\": null,\n    \"population\": 822851.0,\n    \"id\": 1504371270\n  },\n  {\n    \"city\": \"Kenitra\",\n    \"city_ascii\": \"Kenitra\",\n    \"lat\": 34.25,\n    \"lng\": -6.5833,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Rabat-Salé-Kénitra\",\n    \"capital\": null,\n    \"population\": 431282.0,\n    \"id\": 1504534876\n  },\n  {\n    \"city\": \"Tétouan\",\n    \"city_ascii\": \"Tetouan\",\n    \"lat\": 35.5667,\n    \"lng\": -5.3667,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Tanger-Tétouan-Al Hoceïma\",\n    \"capital\": null,\n    \"population\": 380787.0,\n    \"id\": 1504709141\n  },\n  {\n    \"city\": \"El Kelaa des Srarhna\",\n    \"city_ascii\": \"El Kelaa des Srarhna\",\n    \"lat\": 32.0481,\n    \"lng\": -7.4083,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Marrakech-Safi\",\n    \"capital\": null,\n    \"population\": 1450021.0,\n    \"id\": 1504846488\n  },\n  {\n    \"city\": \"Tangier\",\n    \"city_ascii\": \"Tangier\",\n    \"lat\": 35.7767,\n    \"lng\": -5.8039,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Tanger-Tétouan-Al Hoceïma\",\n    \"capital\": \"admin\",\n    \"population\": 947952.0,\n    \"id\": 1504861504\n  },\n  {\n    \"city\": \"Fès\",\n    \"city_ascii\": \"Fes\",\n    \"lat\": 34.0433,\n    \"lng\": -5.0033,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Fès-Meknès\",\n    \"capital\": \"admin\",\n    \"population\": 1112072.0,\n    \"id\": 1504861997\n  },\n  {\n    \"city\": \"Oujda-Angad\",\n    \"city_ascii\": \"Oujda-Angad\",\n    \"lat\": 34.6867,\n    \"lng\": -1.9114,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Oriental\",\n    \"capital\": \"admin\",\n    \"population\": 494252.0,\n    \"id\": 1504891036\n  },\n  {\n    \"city\": \"Sale\",\n    \"city_ascii\": \"Sale\",\n    \"lat\": 34.0333,\n    \"lng\": -6.8,\n    \"country\": \"Morocco\",\n    \"iso2\": \"MA\",\n    \"iso3\": \"MAR\",\n    \"admin_name\": \"Rabat-Salé-Kénitra\",\n    \"capital\": null,\n    \"population\": 850403.0,\n    \"id\": 1504989034\n  },\n  {\n    \"city\": \"Maputo\",\n    \"city_ascii\": \"Maputo\",\n    \"lat\": -25.9667,\n    \"lng\": 32.5833,\n    \"country\": \"Mozambique\",\n    \"iso2\": \"MZ\",\n    \"iso3\": \"MOZ\",\n    \"admin_name\": \"Maputo\",\n    \"capital\": \"primary\",\n    \"population\": 1191613.0,\n    \"id\": 1508074843\n  },\n  {\n    \"city\": \"Beira\",\n    \"city_ascii\": \"Beira\",\n    \"lat\": -19.8333,\n    \"lng\": 34.85,\n    \"country\": \"Mozambique\",\n    \"iso2\": \"MZ\",\n    \"iso3\": \"MOZ\",\n    \"admin_name\": \"Sofala\",\n    \"capital\": \"admin\",\n    \"population\": 436240.0,\n    \"id\": 1508407369\n  },\n  {\n    \"city\": \"António Enes\",\n    \"city_ascii\": \"Antonio Enes\",\n    \"lat\": -16.2333,\n    \"lng\": 39.9167,\n    \"country\": \"Mozambique\",\n    \"iso2\": \"MZ\",\n    \"iso3\": \"MOZ\",\n    \"admin_name\": \"Nampula\",\n    \"capital\": null,\n    \"population\": 347175.0,\n    \"id\": 1508591443\n  },\n  {\n    \"city\": \"Matola\",\n    \"city_ascii\": \"Matola\",\n    \"lat\": -25.9667,\n    \"lng\": 32.4667,\n    \"country\": \"Mozambique\",\n    \"iso2\": \"MZ\",\n    \"iso3\": \"MOZ\",\n    \"admin_name\": \"Maputo\",\n    \"capital\": null,\n    \"population\": 1032197.0,\n    \"id\": 1508768577\n  },\n  {\n    \"city\": \"Nampula\",\n    \"city_ascii\": \"Nampula\",\n    \"lat\": -15.1167,\n    \"lng\": 39.2667,\n    \"country\": \"Mozambique\",\n    \"iso2\": \"MZ\",\n    \"iso3\": \"MOZ\",\n    \"admin_name\": \"Nampula\",\n    \"capital\": \"admin\",\n    \"population\": 743000.0,\n    \"id\": 1508958445\n  },\n  {\n    \"city\": \"Muscat\",\n    \"city_ascii\": \"Muscat\",\n    \"lat\": 23.6139,\n    \"lng\": 58.5922,\n    \"country\": \"Oman\",\n    \"iso2\": \"OM\",\n    \"iso3\": \"OMN\",\n    \"admin_name\": \"Masqaţ\",\n    \"capital\": \"primary\",\n    \"population\": 1421409.0,\n    \"id\": 1512035506\n  },\n  {\n    \"city\": \"Bawshar\",\n    \"city_ascii\": \"Bawshar\",\n    \"lat\": 23.5333,\n    \"lng\": 58.3833,\n    \"country\": \"Oman\",\n    \"iso2\": \"OM\",\n    \"iso3\": \"OMN\",\n    \"admin_name\": \"Masqaţ\",\n    \"capital\": null,\n    \"population\": 383257.0,\n    \"id\": 1512506161\n  },\n  {\n    \"city\": \"Pokhara\",\n    \"city_ascii\": \"Pokhara\",\n    \"lat\": 28.2083,\n    \"lng\": 83.9889,\n    \"country\": \"Nepal\",\n    \"iso2\": \"NP\",\n    \"iso3\": \"NPL\",\n    \"admin_name\": \"Gaṇḍakī\",\n    \"capital\": \"admin\",\n    \"population\": 353841.0,\n    \"id\": 1524416084\n  },\n  {\n    \"city\": \"Kathmandu\",\n    \"city_ascii\": \"Kathmandu\",\n    \"lat\": 27.7172,\n    \"lng\": 85.324,\n    \"country\": \"Nepal\",\n    \"iso2\": \"NP\",\n    \"iso3\": \"NPL\",\n    \"admin_name\": null,\n    \"capital\": \"primary\",\n    \"population\": 975453.0,\n    \"id\": 1524589448\n  },\n  {\n    \"city\": \"Bharatpur\",\n    \"city_ascii\": \"Bharatpur\",\n    \"lat\": 27.6833,\n    \"lng\": 84.4333,\n    \"country\": \"Nepal\",\n    \"iso2\": \"NP\",\n    \"iso3\": \"NPL\",\n    \"admin_name\": null,\n    \"capital\": null,\n    \"population\": 369377.0,\n    \"id\": 1524780273\n  },\n  {\n    \"city\": \"Amsterdam\",\n    \"city_ascii\": \"Amsterdam\",\n    \"lat\": 52.3728,\n    \"lng\": 4.8936,\n    \"country\": \"Netherlands\",\n    \"iso2\": \"NL\",\n    \"iso3\": \"NLD\",\n    \"admin_name\": \"Noord-Holland\",\n    \"capital\": \"primary\",\n    \"population\": 1459402.0,\n    \"id\": 1528355309\n  },\n  {\n    \"city\": \"The Hague\",\n    \"city_ascii\": \"The Hague\",\n    \"lat\": 52.08,\n    \"lng\": 4.31,\n    \"country\": \"Netherlands\",\n    \"iso2\": \"NL\",\n    \"iso3\": \"NLD\",\n    \"admin_name\": \"Zuid-Holland\",\n    \"capital\": \"primary\",\n    \"population\": 548320.0,\n    \"id\": 1528799905\n  },\n  {\n    \"city\": \"Utrecht\",\n    \"city_ascii\": \"Utrecht\",\n    \"lat\": 52.0833,\n    \"lng\": 5.1167,\n    \"country\": \"Netherlands\",\n    \"iso2\": \"NL\",\n    \"iso3\": \"NLD\",\n    \"admin_name\": \"Utrecht\",\n    \"capital\": \"admin\",\n    \"population\": 359370.0,\n    \"id\": 1528871692\n  },\n  {\n    \"city\": \"Rotterdam\",\n    \"city_ascii\": \"Rotterdam\",\n    \"lat\": 51.9167,\n    \"lng\": 4.5,\n    \"country\": \"Netherlands\",\n    \"iso2\": \"NL\",\n    \"iso3\": \"NLD\",\n    \"admin_name\": \"Zuid-Holland\",\n    \"capital\": \"minor\",\n    \"population\": 631155.0,\n    \"id\": 1528892850\n  },\n  {\n    \"city\": \"Christchurch\",\n    \"city_ascii\": \"Christchurch\",\n    \"lat\": -43.531,\n    \"lng\": 172.6365,\n    \"country\": \"New Zealand\",\n    \"iso2\": \"NZ\",\n    \"iso3\": \"NZL\",\n    \"admin_name\": \"Canterbury\",\n    \"capital\": \"admin\",\n    \"population\": 383200.0,\n    \"id\": 1554377228\n  },\n  {\n    \"city\": \"Auckland\",\n    \"city_ascii\": \"Auckland\",\n    \"lat\": -36.8406,\n    \"lng\": 174.74,\n    \"country\": \"New Zealand\",\n    \"iso2\": \"NZ\",\n    \"iso3\": \"NZL\",\n    \"admin_name\": \"Auckland\",\n    \"capital\": \"admin\",\n    \"population\": 1346091.0,\n    \"id\": 1554435911\n  },\n  {\n    \"city\": \"Wellington\",\n    \"city_ascii\": \"Wellington\",\n    \"lat\": -41.2889,\n    \"lng\": 174.7772,\n    \"country\": \"New Zealand\",\n    \"iso2\": \"NZ\",\n    \"iso3\": \"NZL\",\n    \"admin_name\": \"Wellington\",\n    \"capital\": \"primary\",\n    \"population\": 418500.0,\n    \"id\": 1554772152\n  },\n  {\n    \"city\": \"Manukau City\",\n    \"city_ascii\": \"Manukau City\",\n    \"lat\": -37.0,\n    \"lng\": 174.885,\n    \"country\": \"New Zealand\",\n    \"iso2\": \"NZ\",\n    \"iso3\": \"NZL\",\n    \"admin_name\": \"Auckland\",\n    \"capital\": null,\n    \"population\": 375600.0,\n    \"id\": 1554797148\n  },\n  {\n    \"city\": \"Managua\",\n    \"city_ascii\": \"Managua\",\n    \"lat\": 12.1544,\n    \"lng\": -86.2738,\n    \"country\": \"Nicaragua\",\n    \"iso2\": \"NI\",\n    \"iso3\": \"NIC\",\n    \"admin_name\": \"Managua\",\n    \"capital\": \"primary\",\n    \"population\": 1028808.0,\n    \"id\": 1558296252\n  },\n  {\n    \"city\": \"Niamey\",\n    \"city_ascii\": \"Niamey\",\n    \"lat\": 13.515,\n    \"lng\": 2.1175,\n    \"country\": \"Niger\",\n    \"iso2\": \"NE\",\n    \"iso3\": \"NER\",\n    \"admin_name\": \"Niamey\",\n    \"capital\": \"primary\",\n    \"population\": 1026848.0,\n    \"id\": 1562932886\n  },\n  {\n    \"city\": \"Ugep\",\n    \"city_ascii\": \"Ugep\",\n    \"lat\": 5.8,\n    \"lng\": 8.0833,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Cross River\",\n    \"capital\": \"minor\",\n    \"population\": 420000.0,\n    \"id\": 1566000091\n  },\n  {\n    \"city\": \"Uyo\",\n    \"city_ascii\": \"Uyo\",\n    \"lat\": 5.05,\n    \"lng\": 7.9333,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Akwa Ibom\",\n    \"capital\": \"admin\",\n    \"population\": 429900.0,\n    \"id\": 1566061694\n  },\n  {\n    \"city\": \"Port Harcourt\",\n    \"city_ascii\": \"Port Harcourt\",\n    \"lat\": 4.8242,\n    \"lng\": 7.0336,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Rivers\",\n    \"capital\": \"admin\",\n    \"population\": 1865000.0,\n    \"id\": 1566070649\n  },\n  {\n    \"city\": \"Benin City\",\n    \"city_ascii\": \"Benin City\",\n    \"lat\": 6.3333,\n    \"lng\": 5.6222,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Edo\",\n    \"capital\": \"admin\",\n    \"population\": 1147188.0,\n    \"id\": 1566080151\n  },\n  {\n    \"city\": \"Nnewi\",\n    \"city_ascii\": \"Nnewi\",\n    \"lat\": 6.0167,\n    \"lng\": 6.9167,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Anambra\",\n    \"capital\": \"minor\",\n    \"population\": 391227.0,\n    \"id\": 1566097410\n  },\n  {\n    \"city\": \"Ado-Ekiti\",\n    \"city_ascii\": \"Ado-Ekiti\",\n    \"lat\": 7.6167,\n    \"lng\": 5.2167,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Ekiti\",\n    \"capital\": \"admin\",\n    \"population\": 446749.0,\n    \"id\": 1566196391\n  },\n  {\n    \"city\": \"Shagamu\",\n    \"city_ascii\": \"Shagamu\",\n    \"lat\": 6.8333,\n    \"lng\": 3.65,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Ogun\",\n    \"capital\": \"minor\",\n    \"population\": 1132270.0,\n    \"id\": 1566202131\n  },\n  {\n    \"city\": \"Enugu\",\n    \"city_ascii\": \"Enugu\",\n    \"lat\": 6.4528,\n    \"lng\": 7.5111,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Enugu\",\n    \"capital\": \"admin\",\n    \"population\": 715774.0,\n    \"id\": 1566212729\n  },\n  {\n    \"city\": \"Umuahia\",\n    \"city_ascii\": \"Umuahia\",\n    \"lat\": 5.5333,\n    \"lng\": 7.4833,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Abia\",\n    \"capital\": \"admin\",\n    \"population\": 359230.0,\n    \"id\": 1566217980\n  },\n  {\n    \"city\": \"Aba\",\n    \"city_ascii\": \"Aba\",\n    \"lat\": 5.1167,\n    \"lng\": 7.3667,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Abia\",\n    \"capital\": \"minor\",\n    \"population\": 1530000.0,\n    \"id\": 1566262000\n  },\n  {\n    \"city\": \"Zaria\",\n    \"city_ascii\": \"Zaria\",\n    \"lat\": 11.0667,\n    \"lng\": 7.7,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Kaduna\",\n    \"capital\": \"minor\",\n    \"population\": 408198.0,\n    \"id\": 1566287704\n  },\n  {\n    \"city\": \"Warri\",\n    \"city_ascii\": \"Warri\",\n    \"lat\": 5.5167,\n    \"lng\": 5.75,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Delta\",\n    \"capital\": \"minor\",\n    \"population\": 830106.0,\n    \"id\": 1566325734\n  },\n  {\n    \"city\": \"Abuja\",\n    \"city_ascii\": \"Abuja\",\n    \"lat\": 9.0667,\n    \"lng\": 7.4833,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Federal Capital Territory\",\n    \"capital\": \"primary\",\n    \"population\": 3770000.0,\n    \"id\": 1566342270\n  },\n  {\n    \"city\": \"Ibadan\",\n    \"city_ascii\": \"Ibadan\",\n    \"lat\": 7.3964,\n    \"lng\": 3.9167,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Oyo\",\n    \"capital\": \"admin\",\n    \"population\": 3552000.0,\n    \"id\": 1566366407\n  },\n  {\n    \"city\": \"Kaduna\",\n    \"city_ascii\": \"Kaduna\",\n    \"lat\": 10.5167,\n    \"lng\": 7.4333,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Kaduna\",\n    \"capital\": \"admin\",\n    \"population\": 760084.0,\n    \"id\": 1566368729\n  },\n  {\n    \"city\": \"Ogbomoso\",\n    \"city_ascii\": \"Ogbomoso\",\n    \"lat\": 8.1333,\n    \"lng\": 4.25,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Oyo\",\n    \"capital\": \"minor\",\n    \"population\": 1032000.0,\n    \"id\": 1566373448\n  },\n  {\n    \"city\": \"Gusau\",\n    \"city_ascii\": \"Gusau\",\n    \"lat\": 12.15,\n    \"lng\": 6.6667,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Zamfara\",\n    \"capital\": \"admin\",\n    \"population\": 383162.0,\n    \"id\": 1566383682\n  },\n  {\n    \"city\": \"Osogbo\",\n    \"city_ascii\": \"Osogbo\",\n    \"lat\": 7.7667,\n    \"lng\": 4.5667,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Osun\",\n    \"capital\": \"admin\",\n    \"population\": 731000.0,\n    \"id\": 1566395088\n  },\n  {\n    \"city\": \"Saki\",\n    \"city_ascii\": \"Saki\",\n    \"lat\": 8.6667,\n    \"lng\": 3.4,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Oyo\",\n    \"capital\": \"minor\",\n    \"population\": 388225.0,\n    \"id\": 1566404680\n  },\n  {\n    \"city\": \"Kano\",\n    \"city_ascii\": \"Kano\",\n    \"lat\": 12.0,\n    \"lng\": 8.5167,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Kano\",\n    \"capital\": \"admin\",\n    \"population\": 3848885.0,\n    \"id\": 1566422868\n  },\n  {\n    \"city\": \"Ilorin\",\n    \"city_ascii\": \"Ilorin\",\n    \"lat\": 8.5,\n    \"lng\": 4.55,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Kwara\",\n    \"capital\": \"admin\",\n    \"population\": 847582.0,\n    \"id\": 1566480168\n  },\n  {\n    \"city\": \"Bauchi\",\n    \"city_ascii\": \"Bauchi\",\n    \"lat\": 10.3158,\n    \"lng\": 9.8442,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Bauchi\",\n    \"capital\": \"admin\",\n    \"population\": 693700.0,\n    \"id\": 1566483284\n  },\n  {\n    \"city\": \"Ikeja\",\n    \"city_ascii\": \"Ikeja\",\n    \"lat\": 6.6186,\n    \"lng\": 3.3426,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Lagos\",\n    \"capital\": \"admin\",\n    \"population\": 861300.0,\n    \"id\": 1566486388\n  },\n  {\n    \"city\": \"Calabar\",\n    \"city_ascii\": \"Calabar\",\n    \"lat\": 4.9767,\n    \"lng\": 8.3383,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Cross River\",\n    \"capital\": \"admin\",\n    \"population\": 461796.0,\n    \"id\": 1566495489\n  },\n  {\n    \"city\": \"Maiduguri\",\n    \"city_ascii\": \"Maiduguri\",\n    \"lat\": 11.8333,\n    \"lng\": 13.15,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Borno\",\n    \"capital\": \"admin\",\n    \"population\": 1197497.0,\n    \"id\": 1566540296\n  },\n  {\n    \"city\": \"Agege\",\n    \"city_ascii\": \"Agege\",\n    \"lat\": 6.6219,\n    \"lng\": 3.3258,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Lagos\",\n    \"capital\": \"minor\",\n    \"population\": 459939.0,\n    \"id\": 1566564887\n  },\n  {\n    \"city\": \"Akure\",\n    \"city_ascii\": \"Akure\",\n    \"lat\": 7.25,\n    \"lng\": 5.195,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Ondo\",\n    \"capital\": \"admin\",\n    \"population\": 847903.0,\n    \"id\": 1566568277\n  },\n  {\n    \"city\": \"Sokoto\",\n    \"city_ascii\": \"Sokoto\",\n    \"lat\": 13.0622,\n    \"lng\": 5.2339,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Sokoto\",\n    \"capital\": \"admin\",\n    \"population\": 427760.0,\n    \"id\": 1566574518\n  },\n  {\n    \"city\": \"Onitsha\",\n    \"city_ascii\": \"Onitsha\",\n    \"lat\": 6.1667,\n    \"lng\": 6.7833,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Anambra\",\n    \"capital\": \"minor\",\n    \"population\": 1483000.0,\n    \"id\": 1566593483\n  },\n  {\n    \"city\": \"Lagos\",\n    \"city_ascii\": \"Lagos\",\n    \"lat\": 6.455,\n    \"lng\": 3.3841,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Lagos\",\n    \"capital\": \"minor\",\n    \"population\": 16637000.0,\n    \"id\": 1566593751\n  },\n  {\n    \"city\": \"Somolu\",\n    \"city_ascii\": \"Somolu\",\n    \"lat\": 6.5408,\n    \"lng\": 3.3872,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Lagos\",\n    \"capital\": \"minor\",\n    \"population\": 403569.0,\n    \"id\": 1566609760\n  },\n  {\n    \"city\": \"Owerri\",\n    \"city_ascii\": \"Owerri\",\n    \"lat\": 5.4833,\n    \"lng\": 7.0333,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Imo\",\n    \"capital\": \"admin\",\n    \"population\": 908109.0,\n    \"id\": 1566679132\n  },\n  {\n    \"city\": \"Ikare\",\n    \"city_ascii\": \"Ikare\",\n    \"lat\": 7.5167,\n    \"lng\": 5.75,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Ondo\",\n    \"capital\": \"minor\",\n    \"population\": 1099931.0,\n    \"id\": 1566683694\n  },\n  {\n    \"city\": \"Jalingo\",\n    \"city_ascii\": \"Jalingo\",\n    \"lat\": 8.9195,\n    \"lng\": 11.3264,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Taraba\",\n    \"capital\": \"admin\",\n    \"population\": 660213.0,\n    \"id\": 1566732241\n  },\n  {\n    \"city\": \"Ile-Ife\",\n    \"city_ascii\": \"Ile-Ife\",\n    \"lat\": 7.4667,\n    \"lng\": 4.5667,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Osun\",\n    \"capital\": \"minor\",\n    \"population\": 501952.0,\n    \"id\": 1566756897\n  },\n  {\n    \"city\": \"Jos\",\n    \"city_ascii\": \"Jos\",\n    \"lat\": 9.9167,\n    \"lng\": 8.8903,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Plateau\",\n    \"capital\": \"admin\",\n    \"population\": 622802.0,\n    \"id\": 1566773679\n  },\n  {\n    \"city\": \"Yola\",\n    \"city_ascii\": \"Yola\",\n    \"lat\": 9.23,\n    \"lng\": 12.46,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Adamawa\",\n    \"capital\": \"admin\",\n    \"population\": 392854.0,\n    \"id\": 1566782065\n  },\n  {\n    \"city\": \"Owo\",\n    \"city_ascii\": \"Owo\",\n    \"lat\": 7.1961,\n    \"lng\": 5.5864,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Ondo\",\n    \"capital\": \"minor\",\n    \"population\": 425700.0,\n    \"id\": 1566833788\n  },\n  {\n    \"city\": \"Gwoza\",\n    \"city_ascii\": \"Gwoza\",\n    \"lat\": 11.0861,\n    \"lng\": 13.6914,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Borno\",\n    \"capital\": \"minor\",\n    \"population\": 388600.0,\n    \"id\": 1566834535\n  },\n  {\n    \"city\": \"Oyo\",\n    \"city_ascii\": \"Oyo\",\n    \"lat\": 7.85,\n    \"lng\": 3.933,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Oyo\",\n    \"capital\": \"minor\",\n    \"population\": 386723.0,\n    \"id\": 1566930579\n  },\n  {\n    \"city\": \"Ilesa\",\n    \"city_ascii\": \"Ilesa\",\n    \"lat\": 7.6167,\n    \"lng\": 4.7167,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Osun\",\n    \"capital\": \"minor\",\n    \"population\": 384334.0,\n    \"id\": 1566937414\n  },\n  {\n    \"city\": \"Abeokuta\",\n    \"city_ascii\": \"Abeokuta\",\n    \"lat\": 7.1608,\n    \"lng\": 3.3483,\n    \"country\": \"Nigeria\",\n    \"iso2\": \"NG\",\n    \"iso3\": \"NGA\",\n    \"admin_name\": \"Ogun\",\n    \"capital\": \"admin\",\n    \"population\": 888924.0,\n    \"id\": 1566979497\n  },\n  {\n    \"city\": \"Oslo\",\n    \"city_ascii\": \"Oslo\",\n    \"lat\": 59.9133,\n    \"lng\": 10.7389,\n    \"country\": \"Norway\",\n    \"iso2\": \"NO\",\n    \"iso3\": \"NOR\",\n    \"admin_name\": \"Oslo\",\n    \"capital\": \"primary\",\n    \"population\": 1064235.0,\n    \"id\": 1578324706\n  },\n  {\n    \"city\": \"Mardan\",\n    \"city_ascii\": \"Mardan\",\n    \"lat\": 34.2012,\n    \"lng\": 72.0258,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Khyber Pakhtunkhwa\",\n    \"capital\": \"minor\",\n    \"population\": 358604.0,\n    \"id\": 1586001546\n  },\n  {\n    \"city\": \"Dera Ghazi Khan\",\n    \"city_ascii\": \"Dera Ghazi Khan\",\n    \"lat\": 30.0331,\n    \"lng\": 70.64,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 399064.0,\n    \"id\": 1586002238\n  },\n  {\n    \"city\": \"Gujrat\",\n    \"city_ascii\": \"Gujrat\",\n    \"lat\": 32.5739,\n    \"lng\": 74.0789,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 390533.0,\n    \"id\": 1586006990\n  },\n  {\n    \"city\": \"Bahawalpur\",\n    \"city_ascii\": \"Bahawalpur\",\n    \"lat\": 29.3956,\n    \"lng\": 71.6836,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 762111.0,\n    \"id\": 1586038700\n  },\n  {\n    \"city\": \"Karachi\",\n    \"city_ascii\": \"Karachi\",\n    \"lat\": 24.86,\n    \"lng\": 67.01,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Sindh\",\n    \"capital\": \"admin\",\n    \"population\": 15738000.0,\n    \"id\": 1586129469\n  },\n  {\n    \"city\": \"Rahimyar Khan\",\n    \"city_ascii\": \"Rahimyar Khan\",\n    \"lat\": 28.42,\n    \"lng\": 70.3,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": null,\n    \"population\": 420419.0,\n    \"id\": 1586136399\n  },\n  {\n    \"city\": \"Sialkot City\",\n    \"city_ascii\": \"Sialkot City\",\n    \"lat\": 32.4925,\n    \"lng\": 74.5311,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 655852.0,\n    \"id\": 1586141444\n  },\n  {\n    \"city\": \"Hyderabad City\",\n    \"city_ascii\": \"Hyderabad City\",\n    \"lat\": 25.3792,\n    \"lng\": 68.3683,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Sindh\",\n    \"capital\": \"minor\",\n    \"population\": 1732693.0,\n    \"id\": 1586185019\n  },\n  {\n    \"city\": \"Multan\",\n    \"city_ascii\": \"Multan\",\n    \"lat\": 30.1978,\n    \"lng\": 71.4697,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 1871843.0,\n    \"id\": 1586256291\n  },\n  {\n    \"city\": \"Jhang City\",\n    \"city_ascii\": \"Jhang City\",\n    \"lat\": 31.2694,\n    \"lng\": 72.3161,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 414131.0,\n    \"id\": 1586288677\n  },\n  {\n    \"city\": \"Shekhupura\",\n    \"city_ascii\": \"Shekhupura\",\n    \"lat\": 31.7111,\n    \"lng\": 73.9878,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 473129.0,\n    \"id\": 1586291726\n  },\n  {\n    \"city\": \"Islamabad\",\n    \"city_ascii\": \"Islamabad\",\n    \"lat\": 33.6931,\n    \"lng\": 73.0639,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Islamabad\",\n    \"capital\": \"primary\",\n    \"population\": 1014825.0,\n    \"id\": 1586306717\n  },\n  {\n    \"city\": \"Faisalabad\",\n    \"city_ascii\": \"Faisalabad\",\n    \"lat\": 31.4167,\n    \"lng\": 73.0911,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 3203846.0,\n    \"id\": 1586323916\n  },\n  {\n    \"city\": \"Sarai Alamgir\",\n    \"city_ascii\": \"Sarai Alamgir\",\n    \"lat\": 32.9,\n    \"lng\": 73.75,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": null,\n    \"population\": 350288.0,\n    \"id\": 1586338206\n  },\n  {\n    \"city\": \"Cantonment\",\n    \"city_ascii\": \"Cantonment\",\n    \"lat\": 31.5167,\n    \"lng\": 74.3833,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": null,\n    \"population\": 374872.0,\n    \"id\": 1586338974\n  },\n  {\n    \"city\": \"Rawalpindi\",\n    \"city_ascii\": \"Rawalpindi\",\n    \"lat\": 33.6,\n    \"lng\": 73.0333,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 2098231.0,\n    \"id\": 1586344001\n  },\n  {\n    \"city\": \"Sukkur\",\n    \"city_ascii\": \"Sukkur\",\n    \"lat\": 27.7061,\n    \"lng\": 68.8483,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Sindh\",\n    \"capital\": \"minor\",\n    \"population\": 499900.0,\n    \"id\": 1586383591\n  },\n  {\n    \"city\": \"Gujranwala\",\n    \"city_ascii\": \"Gujranwala\",\n    \"lat\": 32.1567,\n    \"lng\": 74.19,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 2027001.0,\n    \"id\": 1586400472\n  },\n  {\n    \"city\": \"Chiniot\",\n    \"city_ascii\": \"Chiniot\",\n    \"lat\": 31.7194,\n    \"lng\": 72.9842,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 477781.0,\n    \"id\": 1586413435\n  },\n  {\n    \"city\": \"Quetta\",\n    \"city_ascii\": \"Quetta\",\n    \"lat\": 30.1833,\n    \"lng\": 67.0,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Balochistan\",\n    \"capital\": \"admin\",\n    \"population\": 1001205.0,\n    \"id\": 1586556108\n  },\n  {\n    \"city\": \"Saidu Sharif\",\n    \"city_ascii\": \"Saidu Sharif\",\n    \"lat\": 34.75,\n    \"lng\": 72.3572,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Khyber Pakhtunkhwa\",\n    \"capital\": \"minor\",\n    \"population\": 1860310.0,\n    \"id\": 1586619596\n  },\n  {\n    \"city\": \"Larkana\",\n    \"city_ascii\": \"Larkana\",\n    \"lat\": 27.5583,\n    \"lng\": 68.2111,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Sindh\",\n    \"capital\": \"minor\",\n    \"population\": 490508.0,\n    \"id\": 1586678302\n  },\n  {\n    \"city\": \"Sargodha\",\n    \"city_ascii\": \"Sargodha\",\n    \"lat\": 32.0836,\n    \"lng\": 72.6711,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"minor\",\n    \"population\": 659862.0,\n    \"id\": 1586696588\n  },\n  {\n    \"city\": \"Bhawana\",\n    \"city_ascii\": \"Bhawana\",\n    \"lat\": 31.5661,\n    \"lng\": 72.6461,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": null,\n    \"population\": 373841.0,\n    \"id\": 1586746564\n  },\n  {\n    \"city\": \"Lahore\",\n    \"city_ascii\": \"Lahore\",\n    \"lat\": 31.5497,\n    \"lng\": 74.3436,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Punjab\",\n    \"capital\": \"admin\",\n    \"population\": 12306000.0,\n    \"id\": 1586801463\n  },\n  {\n    \"city\": \"Peshawar\",\n    \"city_ascii\": \"Peshawar\",\n    \"lat\": 34.0144,\n    \"lng\": 71.5675,\n    \"country\": \"Pakistan\",\n    \"iso2\": \"PK\",\n    \"iso3\": \"PAK\",\n    \"admin_name\": \"Khyber Pakhtunkhwa\",\n    \"capital\": \"admin\",\n    \"population\": 1970042.0,\n    \"id\": 1586851102\n  },\n  {\n    \"city\": \"Panama City\",\n    \"city_ascii\": \"Panama City\",\n    \"lat\": 8.9833,\n    \"lng\": -79.5167,\n    \"country\": \"Panama\",\n    \"iso2\": \"PA\",\n    \"iso3\": \"PAN\",\n    \"admin_name\": \"Panamá\",\n    \"capital\": \"primary\",\n    \"population\": 1500189.0,\n    \"id\": 1591672475\n  },\n  {\n    \"city\": \"Port Moresby\",\n    \"city_ascii\": \"Port Moresby\",\n    \"lat\": -9.4789,\n    \"lng\": 147.1494,\n    \"country\": \"Papua New Guinea\",\n    \"iso2\": \"PG\",\n    \"iso3\": \"PNG\",\n    \"admin_name\": \"National Capital\",\n    \"capital\": \"primary\",\n    \"population\": 700000.0,\n    \"id\": 1598685395\n  },\n  {\n    \"city\": \"Asunción\",\n    \"city_ascii\": \"Asuncion\",\n    \"lat\": -25.3,\n    \"lng\": -57.6333,\n    \"country\": \"Paraguay\",\n    \"iso2\": \"PY\",\n    \"iso3\": \"PRY\",\n    \"admin_name\": \"Asunción\",\n    \"capital\": \"primary\",\n    \"population\": 524190.0,\n    \"id\": 1600057911\n  },\n  {\n    \"city\": \"Cusco\",\n    \"city_ascii\": \"Cusco\",\n    \"lat\": -13.525,\n    \"lng\": -71.9722,\n    \"country\": \"Peru\",\n    \"iso2\": \"PE\",\n    \"iso3\": \"PER\",\n    \"admin_name\": \"Cusco\",\n    \"capital\": \"admin\",\n    \"population\": 428450.0,\n    \"id\": 1604162901\n  },\n  {\n    \"city\": \"Chimbote\",\n    \"city_ascii\": \"Chimbote\",\n    \"lat\": -9.0745,\n    \"lng\": -78.5936,\n    \"country\": \"Peru\",\n    \"iso2\": \"PE\",\n    \"iso3\": \"PER\",\n    \"admin_name\": \"Ancash\",\n    \"capital\": null,\n    \"population\": 497875.0,\n    \"id\": 1604199858\n  },\n  {\n    \"city\": \"Huancayo\",\n    \"city_ascii\": \"Huancayo\",\n    \"lat\": -12.0667,\n    \"lng\": -75.2167,\n    \"country\": \"Peru\",\n    \"iso2\": \"PE\",\n    \"iso3\": \"PER\",\n    \"admin_name\": \"Junín\",\n    \"capital\": \"admin\",\n    \"population\": 378203.0,\n    \"id\": 1604249985\n  },\n  {\n    \"city\": \"Piura\",\n    \"city_ascii\": \"Piura\",\n    \"lat\": -5.2,\n    \"lng\": -80.6333,\n    \"country\": \"Peru\",\n    \"iso2\": \"PE\",\n    \"iso3\": \"PER\",\n    \"admin_name\": \"Piura\",\n    \"capital\": \"admin\",\n    \"population\": 473025.0,\n    \"id\": 1604331641\n  },\n  {\n    \"city\": \"Callao\",\n    \"city_ascii\": \"Callao\",\n    \"lat\": -12.0333,\n    \"lng\": -77.1333,\n    \"country\": \"Peru\",\n    \"iso2\": \"PE\",\n    \"iso3\": \"PER\",\n    \"admin_name\": \"Callao\",\n    \"capital\": \"admin\",\n    \"population\": 1129854.0,\n    \"id\": 1604422141\n  },\n  {\n    \"city\": \"Iquitos\",\n    \"city_ascii\": \"Iquitos\",\n    \"lat\": -3.75,\n    \"lng\": -73.25,\n    \"country\": \"Peru\",\n    \"iso2\": \"PE\",\n    \"iso3\": \"PER\",\n    \"admin_name\": \"Loreto\",\n    \"capital\": \"admin\",\n    \"population\": 377609.0,\n    \"id\": 1604493809\n  },\n  {\n    \"city\": \"Trujillo\",\n    \"city_ascii\": \"Trujillo\",\n    \"lat\": -8.112,\n    \"lng\": -79.0288,\n    \"country\": \"Peru\",\n    \"iso2\": \"PE\",\n    \"iso3\": \"PER\",\n    \"admin_name\": \"La Libertad\",\n    \"capital\": \"admin\",\n    \"population\": 919899.0,\n    \"id\": 1604613706\n  },\n  {\n    \"city\": \"Arequipa\",\n    \"city_ascii\": \"Arequipa\",\n    \"lat\": -16.4,\n    \"lng\": -71.5333,\n    \"country\": \"Peru\",\n    \"iso2\": \"PE\",\n    \"iso3\": \"PER\",\n    \"admin_name\": \"Arequipa\",\n    \"capital\": \"admin\",\n    \"population\": 1008290.0,\n    \"id\": 1604723954\n  },\n  {\n    \"city\": \"Lima\",\n    \"city_ascii\": \"Lima\",\n    \"lat\": -12.06,\n    \"lng\": -77.0375,\n    \"country\": \"Peru\",\n    \"iso2\": \"PE\",\n    \"iso3\": \"PER\",\n    \"admin_name\": \"Lima\",\n    \"capital\": \"primary\",\n    \"population\": 10320000.0,\n    \"id\": 1604728603\n  },\n  {\n    \"city\": \"Chiclayo\",\n    \"city_ascii\": \"Chiclayo\",\n    \"lat\": -6.763,\n    \"lng\": -79.8366,\n    \"country\": \"Peru\",\n    \"iso2\": \"PE\",\n    \"iso3\": \"PER\",\n    \"admin_name\": \"Lambayeque\",\n    \"capital\": \"admin\",\n    \"population\": 552508.0,\n    \"id\": 1604799615\n  },\n  {\n    \"city\": \"Marikina City\",\n    \"city_ascii\": \"Marikina City\",\n    \"lat\": 14.65,\n    \"lng\": 121.1,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Marikina\",\n    \"capital\": \"admin\",\n    \"population\": 456059.0,\n    \"id\": 1608000077\n  },\n  {\n    \"city\": \"Iligan\",\n    \"city_ascii\": \"Iligan\",\n    \"lat\": 8.23,\n    \"lng\": 124.25,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Iligan\",\n    \"capital\": \"admin\",\n    \"population\": 363115.0,\n    \"id\": 1608000268\n  },\n  {\n    \"city\": \"Butuan\",\n    \"city_ascii\": \"Butuan\",\n    \"lat\": 8.9534,\n    \"lng\": 125.5288,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Butuan\",\n    \"capital\": \"admin\",\n    \"population\": 372910.0,\n    \"id\": 1608000722\n  },\n  {\n    \"city\": \"Angeles City\",\n    \"city_ascii\": \"Angeles City\",\n    \"lat\": 15.1472,\n    \"lng\": 120.5847,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Angeles\",\n    \"capital\": \"admin\",\n    \"population\": 462928.0,\n    \"id\": 1608036027\n  },\n  {\n    \"city\": \"Biñan\",\n    \"city_ascii\": \"Binan\",\n    \"lat\": 14.3333,\n    \"lng\": 121.0833,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Laguna\",\n    \"capital\": null,\n    \"population\": 407437.0,\n    \"id\": 1608039268\n  },\n  {\n    \"city\": \"Malabon\",\n    \"city_ascii\": \"Malabon\",\n    \"lat\": 14.66,\n    \"lng\": 120.96,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Malabon\",\n    \"capital\": \"admin\",\n    \"population\": 380522.0,\n    \"id\": 1608045841\n  },\n  {\n    \"city\": \"Cebu City\",\n    \"city_ascii\": \"Cebu City\",\n    \"lat\": 10.32,\n    \"lng\": 123.75,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Cebu\",\n    \"capital\": \"admin\",\n    \"population\": 964169.0,\n    \"id\": 1608136151\n  },\n  {\n    \"city\": \"Baguio City\",\n    \"city_ascii\": \"Baguio City\",\n    \"lat\": 16.4119,\n    \"lng\": 120.5933,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Baguio\",\n    \"capital\": \"admin\",\n    \"population\": 366358.0,\n    \"id\": 1608164766\n  },\n  {\n    \"city\": \"Mandaluyong City\",\n    \"city_ascii\": \"Mandaluyong City\",\n    \"lat\": 14.58,\n    \"lng\": 121.03,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Mandaluyong\",\n    \"capital\": \"admin\",\n    \"population\": 425758.0,\n    \"id\": 1608166320\n  },\n  {\n    \"city\": \"General Santos\",\n    \"city_ascii\": \"General Santos\",\n    \"lat\": 6.1167,\n    \"lng\": 125.1667,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"General Santos\",\n    \"capital\": \"admin\",\n    \"population\": 697315.0,\n    \"id\": 1608171585\n  },\n  {\n    \"city\": \"Zamboanga City\",\n    \"city_ascii\": \"Zamboanga City\",\n    \"lat\": 6.9042,\n    \"lng\": 122.0761,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Zamboanga\",\n    \"capital\": \"admin\",\n    \"population\": 977234.0,\n    \"id\": 1608189351\n  },\n  {\n    \"city\": \"Tondo\",\n    \"city_ascii\": \"Tondo\",\n    \"lat\": 14.617,\n    \"lng\": 120.967,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Manila\",\n    \"capital\": null,\n    \"population\": 654220.0,\n    \"id\": 1608204201\n  },\n  {\n    \"city\": \"Tarlac City\",\n    \"city_ascii\": \"Tarlac City\",\n    \"lat\": 15.4869,\n    \"lng\": 120.59,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Tarlac\",\n    \"capital\": \"admin\",\n    \"population\": 385398.0,\n    \"id\": 1608237027\n  },\n  {\n    \"city\": \"Bacolod\",\n    \"city_ascii\": \"Bacolod\",\n    \"lat\": 10.6765,\n    \"lng\": 122.9509,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Bacolod\",\n    \"capital\": \"admin\",\n    \"population\": 600783.0,\n    \"id\": 1608244137\n  },\n  {\n    \"city\": \"Pasig City\",\n    \"city_ascii\": \"Pasig City\",\n    \"lat\": 14.575,\n    \"lng\": 121.0833,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Pasig\",\n    \"capital\": \"admin\",\n    \"population\": 803159.0,\n    \"id\": 1608278212\n  },\n  {\n    \"city\": \"Cainta\",\n    \"city_ascii\": \"Cainta\",\n    \"lat\": 14.5667,\n    \"lng\": 121.1167,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Rizal\",\n    \"capital\": null,\n    \"population\": 376933.0,\n    \"id\": 1608314665\n  },\n  {\n    \"city\": \"City of Parañaque\",\n    \"city_ascii\": \"City of Paranaque\",\n    \"lat\": 14.47,\n    \"lng\": 121.02,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Parañaque\",\n    \"capital\": \"admin\",\n    \"population\": 689992.0,\n    \"id\": 1608379532\n  },\n  {\n    \"city\": \"Batangas\",\n    \"city_ascii\": \"Batangas\",\n    \"lat\": 13.83,\n    \"lng\": 121.0,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Batangas\",\n    \"capital\": \"admin\",\n    \"population\": 351437.0,\n    \"id\": 1608417616\n  },\n  {\n    \"city\": \"Dasmariñas\",\n    \"city_ascii\": \"Dasmarinas\",\n    \"lat\": 14.3294,\n    \"lng\": 120.9367,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Cavite\",\n    \"capital\": null,\n    \"population\": 703141.0,\n    \"id\": 1608418544\n  },\n  {\n    \"city\": \"Lapu-Lapu City\",\n    \"city_ascii\": \"Lapu-Lapu City\",\n    \"lat\": 10.3127,\n    \"lng\": 123.9488,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Lapu-Lapu\",\n    \"capital\": \"admin\",\n    \"population\": 497604.0,\n    \"id\": 1608430676\n  },\n  {\n    \"city\": \"Pasay City\",\n    \"city_ascii\": \"Pasay City\",\n    \"lat\": 14.55,\n    \"lng\": 121.0,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Pasay\",\n    \"capital\": \"admin\",\n    \"population\": 440656.0,\n    \"id\": 1608448280\n  },\n  {\n    \"city\": \"Muntinlupa City\",\n    \"city_ascii\": \"Muntinlupa City\",\n    \"lat\": 14.38,\n    \"lng\": 121.05,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Muntinlupa\",\n    \"capital\": \"admin\",\n    \"population\": 543445.0,\n    \"id\": 1608473406\n  },\n  {\n    \"city\": \"Valenzuela\",\n    \"city_ascii\": \"Valenzuela\",\n    \"lat\": 14.7,\n    \"lng\": 120.98,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Valenzuela\",\n    \"capital\": \"admin\",\n    \"population\": 714978.0,\n    \"id\": 1608492120\n  },\n  {\n    \"city\": \"Taytay\",\n    \"city_ascii\": \"Taytay\",\n    \"lat\": 14.5692,\n    \"lng\": 121.1325,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Rizal\",\n    \"capital\": null,\n    \"population\": 386451.0,\n    \"id\": 1608530771\n  },\n  {\n    \"city\": \"Rodriguez\",\n    \"city_ascii\": \"Rodriguez\",\n    \"lat\": 14.7167,\n    \"lng\": 121.1167,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Rizal\",\n    \"capital\": null,\n    \"population\": 443954.0,\n    \"id\": 1608543530\n  },\n  {\n    \"city\": \"Las Piñas City\",\n    \"city_ascii\": \"Las Pinas City\",\n    \"lat\": 14.45,\n    \"lng\": 120.98,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Las Piñas\",\n    \"capital\": null,\n    \"population\": 606293.0,\n    \"id\": 1608544537\n  },\n  {\n    \"city\": \"Santa Rosa\",\n    \"city_ascii\": \"Santa Rosa\",\n    \"lat\": 14.3167,\n    \"lng\": 121.1167,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Laguna\",\n    \"capital\": null,\n    \"population\": 414812.0,\n    \"id\": 1608571683\n  },\n  {\n    \"city\": \"Cabuyao\",\n    \"city_ascii\": \"Cabuyao\",\n    \"lat\": 14.275,\n    \"lng\": 121.125,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Laguna\",\n    \"capital\": null,\n    \"population\": 355330.0,\n    \"id\": 1608604441\n  },\n  {\n    \"city\": \"Lipa City\",\n    \"city_ascii\": \"Lipa City\",\n    \"lat\": 13.9411,\n    \"lng\": 121.1622,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Batangas\",\n    \"capital\": null,\n    \"population\": 372931.0,\n    \"id\": 1608615113\n  },\n  {\n    \"city\": \"Manila\",\n    \"city_ascii\": \"Manila\",\n    \"lat\": 14.5958,\n    \"lng\": 120.9772,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Manila\",\n    \"capital\": \"primary\",\n    \"population\": 24922000.0,\n    \"id\": 1608618140\n  },\n  {\n    \"city\": \"Canagatan\",\n    \"city_ascii\": \"Canagatan\",\n    \"lat\": 18.0,\n    \"lng\": 121.8,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Cagayan\",\n    \"capital\": null,\n    \"population\": 1273219.0,\n    \"id\": 1608697675\n  },\n  {\n    \"city\": \"Makati City\",\n    \"city_ascii\": \"Makati City\",\n    \"lat\": 14.5567,\n    \"lng\": 121.0214,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Makati\",\n    \"capital\": \"admin\",\n    \"population\": 629616.0,\n    \"id\": 1608725647\n  },\n  {\n    \"city\": \"Taguig City\",\n    \"city_ascii\": \"Taguig City\",\n    \"lat\": 14.52,\n    \"lng\": 121.05,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Taguig\",\n    \"capital\": \"admin\",\n    \"population\": 886722.0,\n    \"id\": 1608766695\n  },\n  {\n    \"city\": \"Mandaue City\",\n    \"city_ascii\": \"Mandaue City\",\n    \"lat\": 10.3333,\n    \"lng\": 123.9333,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Mandaue\",\n    \"capital\": \"admin\",\n    \"population\": 364116.0,\n    \"id\": 1608794590\n  },\n  {\n    \"city\": \"Imus\",\n    \"city_ascii\": \"Imus\",\n    \"lat\": 14.4297,\n    \"lng\": 120.9367,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Cavite\",\n    \"capital\": null,\n    \"population\": 496794.0,\n    \"id\": 1608802508\n  },\n  {\n    \"city\": \"Antipolo\",\n    \"city_ascii\": \"Antipolo\",\n    \"lat\": 14.5842,\n    \"lng\": 121.1763,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Rizal\",\n    \"capital\": \"admin\",\n    \"population\": 887399.0,\n    \"id\": 1608824345\n  },\n  {\n    \"city\": \"General Trias\",\n    \"city_ascii\": \"General Trias\",\n    \"lat\": 14.3833,\n    \"lng\": 120.8833,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Cavite\",\n    \"capital\": null,\n    \"population\": 450583.0,\n    \"id\": 1608826995\n  },\n  {\n    \"city\": \"Cagayan de Oro\",\n    \"city_ascii\": \"Cagayan de Oro\",\n    \"lat\": 8.4833,\n    \"lng\": 124.65,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Cagayan de Oro\",\n    \"capital\": \"admin\",\n    \"population\": 728402.0,\n    \"id\": 1608831546\n  },\n  {\n    \"city\": \"San Jose del Monte\",\n    \"city_ascii\": \"San Jose del Monte\",\n    \"lat\": 14.8139,\n    \"lng\": 121.0453,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Bulacan\",\n    \"capital\": null,\n    \"population\": 651813.0,\n    \"id\": 1608850554\n  },\n  {\n    \"city\": \"San Fernando\",\n    \"city_ascii\": \"San Fernando\",\n    \"lat\": 15.0333,\n    \"lng\": 120.6833,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Pampanga\",\n    \"capital\": \"admin\",\n    \"population\": 354666.0,\n    \"id\": 1608862124\n  },\n  {\n    \"city\": \"Bacoor\",\n    \"city_ascii\": \"Bacoor\",\n    \"lat\": 14.4624,\n    \"lng\": 120.9645,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Cavite\",\n    \"capital\": null,\n    \"population\": 664625.0,\n    \"id\": 1608869358\n  },\n  {\n    \"city\": \"Iloilo\",\n    \"city_ascii\": \"Iloilo\",\n    \"lat\": 10.7167,\n    \"lng\": 122.5667,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Iloilo\",\n    \"capital\": \"admin\",\n    \"population\": 457626.0,\n    \"id\": 1608875987\n  },\n  {\n    \"city\": \"Caloocan City\",\n    \"city_ascii\": \"Caloocan City\",\n    \"lat\": 14.65,\n    \"lng\": 120.97,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Caloocan\",\n    \"capital\": \"admin\",\n    \"population\": 1661584.0,\n    \"id\": 1608897690\n  },\n  {\n    \"city\": \"Davao\",\n    \"city_ascii\": \"Davao\",\n    \"lat\": 7.0667,\n    \"lng\": 125.6,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Davao\",\n    \"capital\": \"admin\",\n    \"population\": 1776949.0,\n    \"id\": 1608906877\n  },\n  {\n    \"city\": \"Quezon City\",\n    \"city_ascii\": \"Quezon City\",\n    \"lat\": 14.63,\n    \"lng\": 121.03,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Quezon\",\n    \"capital\": \"admin\",\n    \"population\": 2960048.0,\n    \"id\": 1608974097\n  },\n  {\n    \"city\": \"City of Calamba\",\n    \"city_ascii\": \"City of Calamba\",\n    \"lat\": 14.2167,\n    \"lng\": 121.1667,\n    \"country\": \"Philippines\",\n    \"iso2\": \"PH\",\n    \"iso3\": \"PHL\",\n    \"admin_name\": \"Laguna\",\n    \"capital\": null,\n    \"population\": 539671.0,\n    \"id\": 1608985581\n  },\n  {\n    \"city\": \"Warsaw\",\n    \"city_ascii\": \"Warsaw\",\n    \"lat\": 52.23,\n    \"lng\": 21.0111,\n    \"country\": \"Poland\",\n    \"iso2\": \"PL\",\n    \"iso3\": \"POL\",\n    \"admin_name\": \"Mazowieckie\",\n    \"capital\": \"primary\",\n    \"population\": 1860281.0,\n    \"id\": 1616024847\n  },\n  {\n    \"city\": \"Wrocław\",\n    \"city_ascii\": \"Wroclaw\",\n    \"lat\": 51.11,\n    \"lng\": 17.0325,\n    \"country\": \"Poland\",\n    \"iso2\": \"PL\",\n    \"iso3\": \"POL\",\n    \"admin_name\": \"Dolnośląskie\",\n    \"capital\": \"admin\",\n    \"population\": 672929.0,\n    \"id\": 1616108520\n  },\n  {\n    \"city\": \"Kraków\",\n    \"city_ascii\": \"Krakow\",\n    \"lat\": 50.0614,\n    \"lng\": 19.9372,\n    \"country\": \"Poland\",\n    \"iso2\": \"PL\",\n    \"iso3\": \"POL\",\n    \"admin_name\": \"Małopolskie\",\n    \"capital\": \"admin\",\n    \"population\": 800653.0,\n    \"id\": 1616172264\n  },\n  {\n    \"city\": \"Szczecin\",\n    \"city_ascii\": \"Szczecin\",\n    \"lat\": 53.4325,\n    \"lng\": 14.5481,\n    \"country\": \"Poland\",\n    \"iso2\": \"PL\",\n    \"iso3\": \"POL\",\n    \"admin_name\": \"Zachodniopomorskie\",\n    \"capital\": \"admin\",\n    \"population\": 403833.0,\n    \"id\": 1616256546\n  },\n  {\n    \"city\": \"Gdańsk\",\n    \"city_ascii\": \"Gdansk\",\n    \"lat\": 54.3475,\n    \"lng\": 18.6453,\n    \"country\": \"Poland\",\n    \"iso2\": \"PL\",\n    \"iso3\": \"POL\",\n    \"admin_name\": \"Pomorskie\",\n    \"capital\": \"admin\",\n    \"population\": 486022.0,\n    \"id\": 1616406372\n  },\n  {\n    \"city\": \"Bydgoszcz\",\n    \"city_ascii\": \"Bydgoszcz\",\n    \"lat\": 53.1219,\n    \"lng\": 18.0003,\n    \"country\": \"Poland\",\n    \"iso2\": \"PL\",\n    \"iso3\": \"POL\",\n    \"admin_name\": \"Kujawsko-Pomorskie\",\n    \"capital\": \"admin\",\n    \"population\": 346739.0,\n    \"id\": 1616454014\n  },\n  {\n    \"city\": \"Poznań\",\n    \"city_ascii\": \"Poznan\",\n    \"lat\": 52.4083,\n    \"lng\": 16.9336,\n    \"country\": \"Poland\",\n    \"iso2\": \"PL\",\n    \"iso3\": \"POL\",\n    \"admin_name\": \"Wielkopolskie\",\n    \"capital\": \"admin\",\n    \"population\": 546859.0,\n    \"id\": 1616725607\n  },\n  {\n    \"city\": \"Łódź\",\n    \"city_ascii\": \"Lodz\",\n    \"lat\": 51.7769,\n    \"lng\": 19.4547,\n    \"country\": \"Poland\",\n    \"iso2\": \"PL\",\n    \"iso3\": \"POL\",\n    \"admin_name\": \"Łódzkie\",\n    \"capital\": \"admin\",\n    \"population\": 690422.0,\n    \"id\": 1616832750\n  },\n  {\n    \"city\": \"Lublin\",\n    \"city_ascii\": \"Lublin\",\n    \"lat\": 51.25,\n    \"lng\": 22.5667,\n    \"country\": \"Poland\",\n    \"iso2\": \"PL\",\n    \"iso3\": \"POL\",\n    \"admin_name\": \"Lubelskie\",\n    \"capital\": \"admin\",\n    \"population\": 339850.0,\n    \"id\": 1616953501\n  },\n  {\n    \"city\": \"Porto\",\n    \"city_ascii\": \"Porto\",\n    \"lat\": 41.1621,\n    \"lng\": -8.622,\n    \"country\": \"Portugal\",\n    \"iso2\": \"PT\",\n    \"iso3\": \"PRT\",\n    \"admin_name\": \"Porto\",\n    \"capital\": \"admin\",\n    \"population\": 1278210.0,\n    \"id\": 1620356810\n  },\n  {\n    \"city\": \"Aves\",\n    \"city_ascii\": \"Aves\",\n    \"lat\": 41.44,\n    \"lng\": -8.3,\n    \"country\": \"Portugal\",\n    \"iso2\": \"PT\",\n    \"iso3\": \"PRT\",\n    \"admin_name\": \"Porto\",\n    \"capital\": null,\n    \"population\": 425411.0,\n    \"id\": 1620507201\n  },\n  {\n    \"city\": \"Lisbon\",\n    \"city_ascii\": \"Lisbon\",\n    \"lat\": 38.7253,\n    \"lng\": -9.15,\n    \"country\": \"Portugal\",\n    \"iso2\": \"PT\",\n    \"iso3\": \"PRT\",\n    \"admin_name\": \"Lisboa\",\n    \"capital\": \"primary\",\n    \"population\": 2719000.0,\n    \"id\": 1620619017\n  },\n  {\n    \"city\": \"Sintra\",\n    \"city_ascii\": \"Sintra\",\n    \"lat\": 38.7992,\n    \"lng\": -9.3883,\n    \"country\": \"Portugal\",\n    \"iso2\": \"PT\",\n    \"iso3\": \"PRT\",\n    \"admin_name\": \"Lisboa\",\n    \"capital\": \"minor\",\n    \"population\": 377835.0,\n    \"id\": 1620848791\n  },\n  {\n    \"city\": \"Bissau\",\n    \"city_ascii\": \"Bissau\",\n    \"lat\": 11.85,\n    \"lng\": -15.5667,\n    \"country\": \"Guinea-Bissau\",\n    \"iso2\": \"GW\",\n    \"iso3\": \"GNB\",\n    \"admin_name\": \"Bissau\",\n    \"capital\": \"primary\",\n    \"population\": 492004.0,\n    \"id\": 1624168850\n  },\n  {\n    \"city\": \"San Juan\",\n    \"city_ascii\": \"San Juan\",\n    \"lat\": 18.3985,\n    \"lng\": -66.061,\n    \"country\": \"Puerto Rico\",\n    \"iso2\": \"PR\",\n    \"iso3\": \"PRI\",\n    \"admin_name\": \"Puerto Rico\",\n    \"capital\": \"primary\",\n    \"population\": 1915105.0,\n    \"id\": 1630035577\n  },\n  {\n    \"city\": \"Ar Rayyān\",\n    \"city_ascii\": \"Ar Rayyan\",\n    \"lat\": 25.25,\n    \"lng\": 51.4,\n    \"country\": \"Qatar\",\n    \"iso2\": \"QA\",\n    \"iso3\": \"QAT\",\n    \"admin_name\": \"Ar Rayyān\",\n    \"capital\": \"admin\",\n    \"population\": 605712.0,\n    \"id\": 1634097551\n  },\n  {\n    \"city\": \"Doha\",\n    \"city_ascii\": \"Doha\",\n    \"lat\": 25.2867,\n    \"lng\": 51.5333,\n    \"country\": \"Qatar\",\n    \"iso2\": \"QA\",\n    \"iso3\": \"QAT\",\n    \"admin_name\": \"Ad Dawḩah\",\n    \"capital\": \"primary\",\n    \"population\": 1186023.0,\n    \"id\": 1634459660\n  },\n  {\n    \"city\": \"Bucharest\",\n    \"city_ascii\": \"Bucharest\",\n    \"lat\": 44.4325,\n    \"lng\": 26.1039,\n    \"country\": \"Romania\",\n    \"iso2\": \"RO\",\n    \"iso3\": \"ROU\",\n    \"admin_name\": \"Bucureşti\",\n    \"capital\": \"primary\",\n    \"population\": 1883425.0,\n    \"id\": 1642414442\n  },\n  {\n    \"city\": \"Surgut\",\n    \"city_ascii\": \"Surgut\",\n    \"lat\": 61.25,\n    \"lng\": 73.4333,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Khanty-Mansiyskiy Avtonomnyy Okrug-Yugra\",\n    \"capital\": null,\n    \"population\": 395900.0,\n    \"id\": 1643007475\n  },\n  {\n    \"city\": \"Naberezhnyye Chelny\",\n    \"city_ascii\": \"Naberezhnyye Chelny\",\n    \"lat\": 55.7,\n    \"lng\": 52.3333,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Tatarstan\",\n    \"capital\": null,\n    \"population\": 533839.0,\n    \"id\": 1643008493\n  },\n  {\n    \"city\": \"Sochi\",\n    \"city_ascii\": \"Sochi\",\n    \"lat\": 43.5853,\n    \"lng\": 39.7203,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Krasnodarskiy Kray\",\n    \"capital\": null,\n    \"population\": 411524.0,\n    \"id\": 1643009782\n  },\n  {\n    \"city\": \"Kursk\",\n    \"city_ascii\": \"Kursk\",\n    \"lat\": 51.7167,\n    \"lng\": 36.1833,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Kurskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 450977.0,\n    \"id\": 1643011077\n  },\n  {\n    \"city\": \"Nizhniy Novgorod\",\n    \"city_ascii\": \"Nizhniy Novgorod\",\n    \"lat\": 56.3269,\n    \"lng\": 44.0075,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Nizhegorodskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 1264075.0,\n    \"id\": 1643012126\n  },\n  {\n    \"city\": \"Rostov\",\n    \"city_ascii\": \"Rostov\",\n    \"lat\": 47.2333,\n    \"lng\": 39.7,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Rostovskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 1137704.0,\n    \"id\": 1643013518\n  },\n  {\n    \"city\": \"Chita\",\n    \"city_ascii\": \"Chita\",\n    \"lat\": 52.0333,\n    \"lng\": 113.5,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Zabaykal’skiy Kray\",\n    \"capital\": \"admin\",\n    \"population\": 347088.0,\n    \"id\": 1643036673\n  },\n  {\n    \"city\": \"Tyumen\",\n    \"city_ascii\": \"Tyumen\",\n    \"lat\": 57.15,\n    \"lng\": 65.5333,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Tyumenskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 744554.0,\n    \"id\": 1643040435\n  },\n  {\n    \"city\": \"Kazan\",\n    \"city_ascii\": \"Kazan\",\n    \"lat\": 55.7964,\n    \"lng\": 49.1089,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Tatarstan\",\n    \"capital\": \"admin\",\n    \"population\": 1243500.0,\n    \"id\": 1643101260\n  },\n  {\n    \"city\": \"Kirov\",\n    \"city_ascii\": \"Kirov\",\n    \"lat\": 58.6,\n    \"lng\": 49.65,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Kirovskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 501468.0,\n    \"id\": 1643106064\n  },\n  {\n    \"city\": \"Kaluga\",\n    \"city_ascii\": \"Kaluga\",\n    \"lat\": 54.5333,\n    \"lng\": 36.2667,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Kaluzhskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 341892.0,\n    \"id\": 1643161747\n  },\n  {\n    \"city\": \"Cheboksary\",\n    \"city_ascii\": \"Cheboksary\",\n    \"lat\": 56.1333,\n    \"lng\": 47.25,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Chuvashiya\",\n    \"capital\": \"admin\",\n    \"population\": 489498.0,\n    \"id\": 1643163382\n  },\n  {\n    \"city\": \"Khabarovsk\",\n    \"city_ascii\": \"Khabarovsk\",\n    \"lat\": 48.4833,\n    \"lng\": 135.0667,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Khabarovskiy Kray\",\n    \"capital\": \"admin\",\n    \"population\": 616242.0,\n    \"id\": 1643175363\n  },\n  {\n    \"city\": \"Kaliningrad\",\n    \"city_ascii\": \"Kaliningrad\",\n    \"lat\": 54.7003,\n    \"lng\": 20.4531,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Kaliningradskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 475056.0,\n    \"id\": 1643178106\n  },\n  {\n    \"city\": \"Samara\",\n    \"city_ascii\": \"Samara\",\n    \"lat\": 53.2028,\n    \"lng\": 50.1408,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Samarskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 1169719.0,\n    \"id\": 1643205757\n  },\n  {\n    \"city\": \"Ryazan\",\n    \"city_ascii\": \"Ryazan\",\n    \"lat\": 54.63,\n    \"lng\": 39.7425,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Ryazanskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 537622.0,\n    \"id\": 1643205787\n  },\n  {\n    \"city\": \"Bryansk\",\n    \"city_ascii\": \"Bryansk\",\n    \"lat\": 53.25,\n    \"lng\": 34.3667,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Bryanskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 406553.0,\n    \"id\": 1643208827\n  },\n  {\n    \"city\": \"Kemerovo\",\n    \"city_ascii\": \"Kemerovo\",\n    \"lat\": 55.3667,\n    \"lng\": 86.0667,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Kemerovskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 558973.0,\n    \"id\": 1643216311\n  },\n  {\n    \"city\": \"Chelyabinsk\",\n    \"city_ascii\": \"Chelyabinsk\",\n    \"lat\": 55.15,\n    \"lng\": 61.4,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Chelyabinskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 1202371.0,\n    \"id\": 1643224011\n  },\n  {\n    \"city\": \"Tula\",\n    \"city_ascii\": \"Tula\",\n    \"lat\": 54.2,\n    \"lng\": 37.6167,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Tul’skaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 485221.0,\n    \"id\": 1643255206\n  },\n  {\n    \"city\": \"Tolyatti\",\n    \"city_ascii\": \"Tolyatti\",\n    \"lat\": 53.5089,\n    \"lng\": 49.4222,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Samarskaya Oblast’\",\n    \"capital\": null,\n    \"population\": 693072.0,\n    \"id\": 1643256295\n  },\n  {\n    \"city\": \"Tomsk\",\n    \"city_ascii\": \"Tomsk\",\n    \"lat\": 56.4886,\n    \"lng\": 84.9522,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Tomskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 572740.0,\n    \"id\": 1643258928\n  },\n  {\n    \"city\": \"Perm\",\n    \"city_ascii\": \"Perm\",\n    \"lat\": 58.0139,\n    \"lng\": 56.2489,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Permskiy Kray\",\n    \"capital\": \"admin\",\n    \"population\": 1048005.0,\n    \"id\": 1643294442\n  },\n  {\n    \"city\": \"Ivanovo\",\n    \"city_ascii\": \"Ivanovo\",\n    \"lat\": 57.0,\n    \"lng\": 41.0,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Ivanovskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 406933.0,\n    \"id\": 1643297945\n  },\n  {\n    \"city\": \"Moscow\",\n    \"city_ascii\": \"Moscow\",\n    \"lat\": 55.7558,\n    \"lng\": 37.6178,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Moskva\",\n    \"capital\": \"primary\",\n    \"population\": 17332000.0,\n    \"id\": 1643318494\n  },\n  {\n    \"city\": \"Barnaul\",\n    \"city_ascii\": \"Barnaul\",\n    \"lat\": 53.3333,\n    \"lng\": 83.75,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Altayskiy Kray\",\n    \"capital\": \"admin\",\n    \"population\": 633301.0,\n    \"id\": 1643318931\n  },\n  {\n    \"city\": \"Yaroslavl\",\n    \"city_ascii\": \"Yaroslavl\",\n    \"lat\": 57.6167,\n    \"lng\": 39.85,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Yaroslavskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 608079.0,\n    \"id\": 1643338528\n  },\n  {\n    \"city\": \"Omsk\",\n    \"city_ascii\": \"Omsk\",\n    \"lat\": 54.9667,\n    \"lng\": 73.3833,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Omskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 1178391.0,\n    \"id\": 1643360863\n  },\n  {\n    \"city\": \"Novosibirsk\",\n    \"city_ascii\": \"Novosibirsk\",\n    \"lat\": 55.0333,\n    \"lng\": 82.9167,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Novosibirskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 1625631.0,\n    \"id\": 1643399240\n  },\n  {\n    \"city\": \"Belgorod\",\n    \"city_ascii\": \"Belgorod\",\n    \"lat\": 50.6,\n    \"lng\": 36.6,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Belgorodskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 391702.0,\n    \"id\": 1643407900\n  },\n  {\n    \"city\": \"Astrakhan\",\n    \"city_ascii\": \"Astrakhan\",\n    \"lat\": 46.35,\n    \"lng\": 48.035,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Astrakhanskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 532504.0,\n    \"id\": 1643407929\n  },\n  {\n    \"city\": \"Krasnodar\",\n    \"city_ascii\": \"Krasnodar\",\n    \"lat\": 45.0333,\n    \"lng\": 38.9667,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Krasnodarskiy Kray\",\n    \"capital\": \"admin\",\n    \"population\": 948827.0,\n    \"id\": 1643438227\n  },\n  {\n    \"city\": \"Irkutsk\",\n    \"city_ascii\": \"Irkutsk\",\n    \"lat\": 52.2833,\n    \"lng\": 104.2833,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Irkutskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 623736.0,\n    \"id\": 1643439037\n  },\n  {\n    \"city\": \"Tver\",\n    \"city_ascii\": \"Tver\",\n    \"lat\": 56.8578,\n    \"lng\": 35.9219,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Tverskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 424969.0,\n    \"id\": 1643456559\n  },\n  {\n    \"city\": \"Penza\",\n    \"city_ascii\": \"Penza\",\n    \"lat\": 53.2,\n    \"lng\": 45.0,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Penzenskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 523726.0,\n    \"id\": 1643492830\n  },\n  {\n    \"city\": \"Krasnoyarsk\",\n    \"city_ascii\": \"Krasnoyarsk\",\n    \"lat\": 56.0089,\n    \"lng\": 92.8719,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Krasnoyarskiy Kray\",\n    \"capital\": \"admin\",\n    \"population\": 1083865.0,\n    \"id\": 1643544975\n  },\n  {\n    \"city\": \"Saratov\",\n    \"city_ascii\": \"Saratov\",\n    \"lat\": 51.5333,\n    \"lng\": 46.0167,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Saratovskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 845300.0,\n    \"id\": 1643556540\n  },\n  {\n    \"city\": \"Volgograd\",\n    \"city_ascii\": \"Volgograd\",\n    \"lat\": 48.7086,\n    \"lng\": 44.5147,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Volgogradskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 1015586.0,\n    \"id\": 1643577201\n  },\n  {\n    \"city\": \"Makhachkala\",\n    \"city_ascii\": \"Makhachkala\",\n    \"lat\": 42.9833,\n    \"lng\": 47.4833,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Dagestan\",\n    \"capital\": \"admin\",\n    \"population\": 592976.0,\n    \"id\": 1643580480\n  },\n  {\n    \"city\": \"Yekaterinburg\",\n    \"city_ascii\": \"Yekaterinburg\",\n    \"lat\": 56.8356,\n    \"lng\": 60.6128,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Sverdlovskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 1468833.0,\n    \"id\": 1643582706\n  },\n  {\n    \"city\": \"Saint Petersburg\",\n    \"city_ascii\": \"Saint Petersburg\",\n    \"lat\": 59.95,\n    \"lng\": 30.3167,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Sankt-Peterburg\",\n    \"capital\": \"admin\",\n    \"population\": 5384342.0,\n    \"id\": 1643616350\n  },\n  {\n    \"city\": \"Novokuznetsk\",\n    \"city_ascii\": \"Novokuznetsk\",\n    \"lat\": 53.7667,\n    \"lng\": 87.1333,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Kemerovskaya Oblast’\",\n    \"capital\": null,\n    \"population\": 552105.0,\n    \"id\": 1643628717\n  },\n  {\n    \"city\": \"Ulyanovsk\",\n    \"city_ascii\": \"Ulyanovsk\",\n    \"lat\": 54.3167,\n    \"lng\": 48.3667,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Ul’yanovskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 624518.0,\n    \"id\": 1643668944\n  },\n  {\n    \"city\": \"Orenburg\",\n    \"city_ascii\": \"Orenburg\",\n    \"lat\": 51.7667,\n    \"lng\": 55.1,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Orenburgskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 564773.0,\n    \"id\": 1643685056\n  },\n  {\n    \"city\": \"Vladimir\",\n    \"city_ascii\": \"Vladimir\",\n    \"lat\": 56.1286,\n    \"lng\": 40.4058,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Vladimirskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 356168.0,\n    \"id\": 1643712167\n  },\n  {\n    \"city\": \"Ufa\",\n    \"city_ascii\": \"Ufa\",\n    \"lat\": 54.7261,\n    \"lng\": 55.9475,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Bashkortostan\",\n    \"capital\": \"admin\",\n    \"population\": 1115560.0,\n    \"id\": 1643722928\n  },\n  {\n    \"city\": \"Lipetsk\",\n    \"city_ascii\": \"Lipetsk\",\n    \"lat\": 52.6167,\n    \"lng\": 39.6,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Lipetskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 510439.0,\n    \"id\": 1643772906\n  },\n  {\n    \"city\": \"Ulan-Ude\",\n    \"city_ascii\": \"Ulan-Ude\",\n    \"lat\": 51.8272,\n    \"lng\": 107.6064,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Buryatiya\",\n    \"capital\": \"admin\",\n    \"population\": 439128.0,\n    \"id\": 1643774900\n  },\n  {\n    \"city\": \"Arkhangelsk\",\n    \"city_ascii\": \"Arkhangelsk\",\n    \"lat\": 64.55,\n    \"lng\": 40.5333,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Arkhangel’skaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 351488.0,\n    \"id\": 1643797198\n  },\n  {\n    \"city\": \"Voronezh\",\n    \"city_ascii\": \"Voronezh\",\n    \"lat\": 51.6717,\n    \"lng\": 39.2106,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Voronezhskaya Oblast’\",\n    \"capital\": \"admin\",\n    \"population\": 1050602.0,\n    \"id\": 1643811064\n  },\n  {\n    \"city\": \"Vladivostok\",\n    \"city_ascii\": \"Vladivostok\",\n    \"lat\": 43.1333,\n    \"lng\": 131.9,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Primorskiy Kray\",\n    \"capital\": \"admin\",\n    \"population\": 606589.0,\n    \"id\": 1643832017\n  },\n  {\n    \"city\": \"Stavropol\",\n    \"city_ascii\": \"Stavropol\",\n    \"lat\": 45.05,\n    \"lng\": 41.9833,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Stavropol’skiy Kray\",\n    \"capital\": \"admin\",\n    \"population\": 450680.0,\n    \"id\": 1643947228\n  },\n  {\n    \"city\": \"Izhevsk\",\n    \"city_ascii\": \"Izhevsk\",\n    \"lat\": 56.85,\n    \"lng\": 53.2167,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Udmurtiya\",\n    \"capital\": \"admin\",\n    \"population\": 646277.0,\n    \"id\": 1643983138\n  },\n  {\n    \"city\": \"Magnitogorsk\",\n    \"city_ascii\": \"Magnitogorsk\",\n    \"lat\": 53.3833,\n    \"lng\": 59.0333,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Chelyabinskaya Oblast’\",\n    \"capital\": null,\n    \"population\": 418241.0,\n    \"id\": 1643987830\n  },\n  {\n    \"city\": \"Balashikha\",\n    \"city_ascii\": \"Balashikha\",\n    \"lat\": 55.8167,\n    \"lng\": 37.9667,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Moskovskaya Oblast’\",\n    \"capital\": null,\n    \"population\": 468221.0,\n    \"id\": 1643989845\n  },\n  {\n    \"city\": \"Nizhniy Tagil\",\n    \"city_ascii\": \"Nizhniy Tagil\",\n    \"lat\": 57.9167,\n    \"lng\": 59.9667,\n    \"country\": \"Russia\",\n    \"iso2\": \"RU\",\n    \"iso3\": \"RUS\",\n    \"admin_name\": \"Sverdlovskaya Oblast’\",\n    \"capital\": null,\n    \"population\": 355693.0,\n    \"id\": 1643992310\n  },\n  {\n    \"city\": \"Kigali\",\n    \"city_ascii\": \"Kigali\",\n    \"lat\": -1.9536,\n    \"lng\": 30.0606,\n    \"country\": \"Rwanda\",\n    \"iso2\": \"RW\",\n    \"iso3\": \"RWA\",\n    \"admin_name\": \"Kigali\",\n    \"capital\": \"primary\",\n    \"population\": 1156663.0,\n    \"id\": 1646923541\n  },\n  {\n    \"city\": \"Al Qaţīf\",\n    \"city_ascii\": \"Al Qatif\",\n    \"lat\": 26.556,\n    \"lng\": 49.996,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Ash Sharqīyah\",\n    \"capital\": null,\n    \"population\": 524182.0,\n    \"id\": 1682001245\n  },\n  {\n    \"city\": \"Mecca\",\n    \"city_ascii\": \"Mecca\",\n    \"lat\": 21.4225,\n    \"lng\": 39.8233,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Makkah al Mukarramah\",\n    \"capital\": \"admin\",\n    \"population\": 1675368.0,\n    \"id\": 1682169241\n  },\n  {\n    \"city\": \"Ḩā’il\",\n    \"city_ascii\": \"Ha'il\",\n    \"lat\": 27.5167,\n    \"lng\": 41.6833,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Ḩā’il\",\n    \"capital\": \"admin\",\n    \"population\": 385257.0,\n    \"id\": 1682249750\n  },\n  {\n    \"city\": \"Medina\",\n    \"city_ascii\": \"Medina\",\n    \"lat\": 24.47,\n    \"lng\": 39.61,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Al Madīnah al Munawwarah\",\n    \"capital\": \"admin\",\n    \"population\": 1180770.0,\n    \"id\": 1682345785\n  },\n  {\n    \"city\": \"Ḩafr al Bāţin\",\n    \"city_ascii\": \"Hafr al Batin\",\n    \"lat\": 28.4342,\n    \"lng\": 45.9636,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Ash Sharqīyah\",\n    \"capital\": null,\n    \"population\": 600000.0,\n    \"id\": 1682394909\n  },\n  {\n    \"city\": \"Ad Dammām\",\n    \"city_ascii\": \"Ad Dammam\",\n    \"lat\": 26.4333,\n    \"lng\": 50.1,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Ash Sharqīyah\",\n    \"capital\": \"admin\",\n    \"population\": 903312.0,\n    \"id\": 1682452296\n  },\n  {\n    \"city\": \"Buraydah\",\n    \"city_ascii\": \"Buraydah\",\n    \"lat\": 26.3333,\n    \"lng\": 43.9667,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Al Qaşīm\",\n    \"capital\": \"admin\",\n    \"population\": 467410.0,\n    \"id\": 1682470726\n  },\n  {\n    \"city\": \"Al Ḩillah\",\n    \"city_ascii\": \"Al Hillah\",\n    \"lat\": 23.4895,\n    \"lng\": 46.7564,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Ar Riyāḑ\",\n    \"capital\": null,\n    \"population\": 594605.0,\n    \"id\": 1682494753\n  },\n  {\n    \"city\": \"Al Jubayl\",\n    \"city_ascii\": \"Al Jubayl\",\n    \"lat\": 27.0,\n    \"lng\": 49.6544,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Ash Sharqīyah\",\n    \"capital\": null,\n    \"population\": 392948.0,\n    \"id\": 1682564079\n  },\n  {\n    \"city\": \"Tabūk\",\n    \"city_ascii\": \"Tabuk\",\n    \"lat\": 28.3972,\n    \"lng\": 36.5789,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Tabūk\",\n    \"capital\": \"admin\",\n    \"population\": 547957.0,\n    \"id\": 1682590992\n  },\n  {\n    \"city\": \"Jeddah\",\n    \"city_ascii\": \"Jeddah\",\n    \"lat\": 21.5433,\n    \"lng\": 39.1728,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Makkah al Mukarramah\",\n    \"capital\": null,\n    \"population\": 3976000.0,\n    \"id\": 1682926944\n  },\n  {\n    \"city\": \"Al Kharj\",\n    \"city_ascii\": \"Al Kharj\",\n    \"lat\": 24.1483,\n    \"lng\": 47.305,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Ar Riyāḑ\",\n    \"capital\": null,\n    \"population\": 376325.0,\n    \"id\": 1682947408\n  },\n  {\n    \"city\": \"Aţ Ţā’if\",\n    \"city_ascii\": \"At Ta'if\",\n    \"lat\": 21.2751,\n    \"lng\": 40.4062,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Makkah al Mukarramah\",\n    \"capital\": null,\n    \"population\": 579970.0,\n    \"id\": 1682956102\n  },\n  {\n    \"city\": \"Al Hufūf\",\n    \"city_ascii\": \"Al Hufuf\",\n    \"lat\": 25.3833,\n    \"lng\": 49.5833,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Ash Sharqīyah\",\n    \"capital\": null,\n    \"population\": 660788.0,\n    \"id\": 1682958157\n  },\n  {\n    \"city\": \"Riyadh\",\n    \"city_ascii\": \"Riyadh\",\n    \"lat\": 24.6333,\n    \"lng\": 46.7167,\n    \"country\": \"Saudi Arabia\",\n    \"iso2\": \"SA\",\n    \"iso3\": \"SAU\",\n    \"admin_name\": \"Ar Riyāḑ\",\n    \"capital\": \"primary\",\n    \"population\": 7237000.0,\n    \"id\": 1682999334\n  },\n  {\n    \"city\": \"Pikine\",\n    \"city_ascii\": \"Pikine\",\n    \"lat\": 14.75,\n    \"lng\": -17.4,\n    \"country\": \"Senegal\",\n    \"iso2\": \"SN\",\n    \"iso3\": \"SEN\",\n    \"admin_name\": \"Dakar\",\n    \"capital\": null,\n    \"population\": 1170791.0,\n    \"id\": 1686165071\n  },\n  {\n    \"city\": \"Thiès\",\n    \"city_ascii\": \"Thies\",\n    \"lat\": 14.7833,\n    \"lng\": -16.9167,\n    \"country\": \"Senegal\",\n    \"iso2\": \"SN\",\n    \"iso3\": \"SEN\",\n    \"admin_name\": \"Thiès\",\n    \"capital\": \"admin\",\n    \"population\": 394544.0,\n    \"id\": 1686527948\n  },\n  {\n    \"city\": \"Dakar\",\n    \"city_ascii\": \"Dakar\",\n    \"lat\": 14.6928,\n    \"lng\": -17.4467,\n    \"country\": \"Senegal\",\n    \"iso2\": \"SN\",\n    \"iso3\": \"SEN\",\n    \"admin_name\": \"Dakar\",\n    \"capital\": \"primary\",\n    \"population\": 1438725.0,\n    \"id\": 1686604760\n  },\n  {\n    \"city\": \"Touba\",\n    \"city_ascii\": \"Touba\",\n    \"lat\": 14.8667,\n    \"lng\": -15.8833,\n    \"country\": \"Senegal\",\n    \"iso2\": \"SN\",\n    \"iso3\": \"SEN\",\n    \"admin_name\": \"Diourbel\",\n    \"capital\": null,\n    \"population\": 529176.0,\n    \"id\": 1686956738\n  },\n  {\n    \"city\": \"Novi Sad\",\n    \"city_ascii\": \"Novi Sad\",\n    \"lat\": 45.2542,\n    \"lng\": 19.8425,\n    \"country\": \"Serbia\",\n    \"iso2\": \"RS\",\n    \"iso3\": \"SRB\",\n    \"admin_name\": \"Novi Sad\",\n    \"capital\": \"admin\",\n    \"population\": 380000.0,\n    \"id\": 1688169087\n  },\n  {\n    \"city\": \"Belgrade\",\n    \"city_ascii\": \"Belgrade\",\n    \"lat\": 44.82,\n    \"lng\": 20.46,\n    \"country\": \"Serbia\",\n    \"iso2\": \"RS\",\n    \"iso3\": \"SRB\",\n    \"admin_name\": \"Beograd\",\n    \"capital\": \"primary\",\n    \"population\": 1378682.0,\n    \"id\": 1688374696\n  },\n  {\n    \"city\": \"Freetown\",\n    \"city_ascii\": \"Freetown\",\n    \"lat\": 8.4844,\n    \"lng\": -13.2344,\n    \"country\": \"Sierra Leone\",\n    \"iso2\": \"SL\",\n    \"iso3\": \"SLE\",\n    \"admin_name\": \"Western Area\",\n    \"capital\": \"primary\",\n    \"population\": 951000.0,\n    \"id\": 1694085071\n  },\n  {\n    \"city\": \"Singapore\",\n    \"city_ascii\": \"Singapore\",\n    \"lat\": 1.3,\n    \"lng\": 103.8,\n    \"country\": \"Singapore\",\n    \"iso2\": \"SG\",\n    \"iso3\": \"SGP\",\n    \"admin_name\": null,\n    \"capital\": \"primary\",\n    \"population\": 5983000.0,\n    \"id\": 1702341327\n  },\n  {\n    \"city\": \"Bratislava\",\n    \"city_ascii\": \"Bratislava\",\n    \"lat\": 48.1439,\n    \"lng\": 17.1097,\n    \"country\": \"Slovakia\",\n    \"iso2\": \"SK\",\n    \"iso3\": \"SVK\",\n    \"admin_name\": \"Bratislava\",\n    \"capital\": \"primary\",\n    \"population\": 475503.0,\n    \"id\": 1703195001\n  },\n  {\n    \"city\": \"Haiphong\",\n    \"city_ascii\": \"Haiphong\",\n    \"lat\": 20.8651,\n    \"lng\": 106.6838,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Hải Phòng\",\n    \"capital\": \"admin\",\n    \"population\": 2103500.0,\n    \"id\": 1704000623\n  },\n  {\n    \"city\": \"Huế\",\n    \"city_ascii\": \"Hue\",\n    \"lat\": 16.4667,\n    \"lng\": 107.5792,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Thừa Thiên-Huế\",\n    \"capital\": \"admin\",\n    \"population\": 652572.0,\n    \"id\": 1704016023\n  },\n  {\n    \"city\": \"Thanh Hóa\",\n    \"city_ascii\": \"Thanh Hoa\",\n    \"lat\": 19.8075,\n    \"lng\": 105.7764,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Thanh Hóa\",\n    \"capital\": \"admin\",\n    \"population\": 393294.0,\n    \"id\": 1704016079\n  },\n  {\n    \"city\": \"Bắc Ninh\",\n    \"city_ascii\": \"Bac Ninh\",\n    \"lat\": 21.1833,\n    \"lng\": 106.05,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Bắc Ninh\",\n    \"capital\": \"admin\",\n    \"population\": 520000.0,\n    \"id\": 1704025181\n  },\n  {\n    \"city\": \"Thủ Đức\",\n    \"city_ascii\": \"Thu Duc\",\n    \"lat\": 10.8266,\n    \"lng\": 106.7609,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Hồ Chí Minh\",\n    \"capital\": \"minor\",\n    \"population\": 1013795.0,\n    \"id\": 1704361621\n  },\n  {\n    \"city\": \"Hanoi\",\n    \"city_ascii\": \"Hanoi\",\n    \"lat\": 21.0283,\n    \"lng\": 105.8542,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Hà Nội\",\n    \"capital\": \"primary\",\n    \"population\": 8246600.0,\n    \"id\": 1704413791\n  },\n  {\n    \"city\": \"Nha Trang\",\n    \"city_ascii\": \"Nha Trang\",\n    \"lat\": 12.245,\n    \"lng\": 109.1917,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Khánh Hòa\",\n    \"capital\": \"admin\",\n    \"population\": 392279.0,\n    \"id\": 1704497901\n  },\n  {\n    \"city\": \"Buôn Ma Thuột\",\n    \"city_ascii\": \"Buon Ma Thuot\",\n    \"lat\": 12.6667,\n    \"lng\": 108.05,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Đắk Lắk\",\n    \"capital\": \"admin\",\n    \"population\": 340000.0,\n    \"id\": 1704542086\n  },\n  {\n    \"city\": \"Vũng Tàu\",\n    \"city_ascii\": \"Vung Tau\",\n    \"lat\": 10.3833,\n    \"lng\": 107.1167,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Bà Rịa-Vũng Tàu\",\n    \"capital\": \"admin\",\n    \"population\": 341552.0,\n    \"id\": 1704581438\n  },\n  {\n    \"city\": \"Tân An\",\n    \"city_ascii\": \"Tan An\",\n    \"lat\": 10.905,\n    \"lng\": 106.6994,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Hồ Chí Minh\",\n    \"capital\": null,\n    \"population\": 618984.0,\n    \"id\": 1704599287\n  },\n  {\n    \"city\": \"Ho Chi Minh City\",\n    \"city_ascii\": \"Ho Chi Minh City\",\n    \"lat\": 10.7756,\n    \"lng\": 106.7019,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Hồ Chí Minh\",\n    \"capital\": \"admin\",\n    \"population\": 15136000.0,\n    \"id\": 1704774326\n  },\n  {\n    \"city\": \"Cần Thơ\",\n    \"city_ascii\": \"Can Tho\",\n    \"lat\": 10.0333,\n    \"lng\": 105.7833,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Cần Thơ\",\n    \"capital\": \"admin\",\n    \"population\": 1237300.0,\n    \"id\": 1704783472\n  },\n  {\n    \"city\": \"Biên Hòa\",\n    \"city_ascii\": \"Bien Hoa\",\n    \"lat\": 10.95,\n    \"lng\": 106.8167,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Đồng Nai\",\n    \"capital\": \"admin\",\n    \"population\": 1104000.0,\n    \"id\": 1704863046\n  },\n  {\n    \"city\": \"Thủ Dầu Một\",\n    \"city_ascii\": \"Thu Dau Mot\",\n    \"lat\": 10.9667,\n    \"lng\": 106.65,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Bình Dương\",\n    \"capital\": \"admin\",\n    \"population\": 417000.0,\n    \"id\": 1704890399\n  },\n  {\n    \"city\": \"Nam Định\",\n    \"city_ascii\": \"Nam Dinh\",\n    \"lat\": 20.42,\n    \"lng\": 106.1683,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Nam Định\",\n    \"capital\": \"admin\",\n    \"population\": 352108.0,\n    \"id\": 1704906277\n  },\n  {\n    \"city\": \"Hải Dương\",\n    \"city_ascii\": \"Hai Duong\",\n    \"lat\": 20.9397,\n    \"lng\": 106.3306,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Hải Dương\",\n    \"capital\": \"admin\",\n    \"population\": 507469.0,\n    \"id\": 1704909566\n  },\n  {\n    \"city\": \"Vinh\",\n    \"city_ascii\": \"Vinh\",\n    \"lat\": 18.6667,\n    \"lng\": 105.6667,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Nghệ An\",\n    \"capital\": \"admin\",\n    \"population\": 490000.0,\n    \"id\": 1704960059\n  },\n  {\n    \"city\": \"Quảng Hà\",\n    \"city_ascii\": \"Quang Ha\",\n    \"lat\": 15.9333,\n    \"lng\": 108.2667,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Quảng Nam\",\n    \"capital\": null,\n    \"population\": 1000000.0,\n    \"id\": 1704966442\n  },\n  {\n    \"city\": \"Tân Uyên\",\n    \"city_ascii\": \"Tan Uyen\",\n    \"lat\": 11.0508,\n    \"lng\": 106.7636,\n    \"country\": \"Vietnam\",\n    \"iso2\": \"VN\",\n    \"iso3\": \"VNM\",\n    \"admin_name\": \"Bình Dương\",\n    \"capital\": \"minor\",\n    \"population\": 466053.0,\n    \"id\": 1704985934\n  },\n  {\n    \"city\": \"Boosaaso\",\n    \"city_ascii\": \"Boosaaso\",\n    \"lat\": 11.2886,\n    \"lng\": 49.1819,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Bari\",\n    \"capital\": \"admin\",\n    \"population\": 2000000.0,\n    \"id\": 1706054548\n  },\n  {\n    \"city\": \"Gaalkacyo\",\n    \"city_ascii\": \"Gaalkacyo\",\n    \"lat\": 6.7697,\n    \"lng\": 47.4308,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Mudug\",\n    \"capital\": \"admin\",\n    \"population\": 950000.0,\n    \"id\": 1706067930\n  },\n  {\n    \"city\": \"Kismaayo\",\n    \"city_ascii\": \"Kismaayo\",\n    \"lat\": -0.3581,\n    \"lng\": 42.5453,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Jubbada Hoose\",\n    \"capital\": \"admin\",\n    \"population\": 358000.0,\n    \"id\": 1706091701\n  },\n  {\n    \"city\": \"Marka\",\n    \"city_ascii\": \"Marka\",\n    \"lat\": 1.6833,\n    \"lng\": 44.75,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Shabeellaha Hoose\",\n    \"capital\": \"admin\",\n    \"population\": 499000.0,\n    \"id\": 1706165964\n  },\n  {\n    \"city\": \"Buurhakaba\",\n    \"city_ascii\": \"Buurhakaba\",\n    \"lat\": 2.7833,\n    \"lng\": 44.0833,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Bay\",\n    \"capital\": \"minor\",\n    \"population\": 360795.0,\n    \"id\": 1706176225\n  },\n  {\n    \"city\": \"Burco\",\n    \"city_ascii\": \"Burco\",\n    \"lat\": 9.5279,\n    \"lng\": 45.5345,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Togdheer\",\n    \"capital\": \"admin\",\n    \"population\": 750211.0,\n    \"id\": 1706322754\n  },\n  {\n    \"city\": \"Qardho\",\n    \"city_ascii\": \"Qardho\",\n    \"lat\": 9.5,\n    \"lng\": 49.0833,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Bari\",\n    \"capital\": null,\n    \"population\": 365000.0,\n    \"id\": 1706405003\n  },\n  {\n    \"city\": \"Cadaado\",\n    \"city_ascii\": \"Cadaado\",\n    \"lat\": 6.1403,\n    \"lng\": 46.6256,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Galguduud\",\n    \"capital\": null,\n    \"population\": 534023.0,\n    \"id\": 1706406560\n  },\n  {\n    \"city\": \"Garoowe\",\n    \"city_ascii\": \"Garoowe\",\n    \"lat\": 8.4,\n    \"lng\": 48.4667,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Nugaal\",\n    \"capital\": \"admin\",\n    \"population\": 385000.0,\n    \"id\": 1706512367\n  },\n  {\n    \"city\": \"Baidoa\",\n    \"city_ascii\": \"Baidoa\",\n    \"lat\": 3.1167,\n    \"lng\": 43.65,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Bay\",\n    \"capital\": \"admin\",\n    \"population\": 950000.0,\n    \"id\": 1706563100\n  },\n  {\n    \"city\": \"Baardheere\",\n    \"city_ascii\": \"Baardheere\",\n    \"lat\": 2.3333,\n    \"lng\": 42.2833,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Gedo\",\n    \"capital\": null,\n    \"population\": 755500.0,\n    \"id\": 1706822684\n  },\n  {\n    \"city\": \"Hargeysa\",\n    \"city_ascii\": \"Hargeysa\",\n    \"lat\": 9.5631,\n    \"lng\": 44.0675,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Woqooyi Galbeed\",\n    \"capital\": \"admin\",\n    \"population\": 1200000.0,\n    \"id\": 1706832021\n  },\n  {\n    \"city\": \"Berbera\",\n    \"city_ascii\": \"Berbera\",\n    \"lat\": 10.4356,\n    \"lng\": 45.0164,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Woqooyi Galbeed\",\n    \"capital\": null,\n    \"population\": 478000.0,\n    \"id\": 1706893125\n  },\n  {\n    \"city\": \"Mogadishu\",\n    \"city_ascii\": \"Mogadishu\",\n    \"lat\": 2.0392,\n    \"lng\": 45.3419,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Banaadir\",\n    \"capital\": \"primary\",\n    \"population\": 4249083.0,\n    \"id\": 1706893395\n  },\n  {\n    \"city\": \"Ceel Baraf\",\n    \"city_ascii\": \"Ceel Baraf\",\n    \"lat\": 3.2073,\n    \"lng\": 45.7587,\n    \"country\": \"Somalia\",\n    \"iso2\": \"SO\",\n    \"iso3\": \"SOM\",\n    \"admin_name\": \"Shabeellaha Dhexe\",\n    \"capital\": null,\n    \"population\": 384630.0,\n    \"id\": 1706959191\n  },\n  {\n    \"city\": \"Newcastle\",\n    \"city_ascii\": \"Newcastle\",\n    \"lat\": -27.7464,\n    \"lng\": 29.9328,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"KwaZulu-Natal\",\n    \"capital\": null,\n    \"population\": 363236.0,\n    \"id\": 1710031016\n  },\n  {\n    \"city\": \"Durban\",\n    \"city_ascii\": \"Durban\",\n    \"lat\": -29.8833,\n    \"lng\": 31.05,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"KwaZulu-Natal\",\n    \"capital\": null,\n    \"population\": 595061.0,\n    \"id\": 1710149138\n  },\n  {\n    \"city\": \"Pretoria\",\n    \"city_ascii\": \"Pretoria\",\n    \"lat\": -25.7461,\n    \"lng\": 28.1881,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"Gauteng\",\n    \"capital\": \"primary\",\n    \"population\": 741651.0,\n    \"id\": 1710176249\n  },\n  {\n    \"city\": \"Vereeniging\",\n    \"city_ascii\": \"Vereeniging\",\n    \"lat\": -26.6736,\n    \"lng\": 27.9319,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"Gauteng\",\n    \"capital\": null,\n    \"population\": 1074000.0,\n    \"id\": 1710271883\n  },\n  {\n    \"city\": \"Kimberley\",\n    \"city_ascii\": \"Kimberley\",\n    \"lat\": -28.7383,\n    \"lng\": 24.7639,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"Northern Cape\",\n    \"capital\": \"admin\",\n    \"population\": 500757.0,\n    \"id\": 1710282622\n  },\n  {\n    \"city\": \"Rustenburg\",\n    \"city_ascii\": \"Rustenburg\",\n    \"lat\": -25.6667,\n    \"lng\": 27.2428,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"North West\",\n    \"capital\": null,\n    \"population\": 549575.0,\n    \"id\": 1710326039\n  },\n  {\n    \"city\": \"Welkom\",\n    \"city_ascii\": \"Welkom\",\n    \"lat\": -27.9831,\n    \"lng\": 26.7208,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"Free State\",\n    \"capital\": null,\n    \"population\": 431944.0,\n    \"id\": 1710480365\n  },\n  {\n    \"city\": \"Johannesburg\",\n    \"city_ascii\": \"Johannesburg\",\n    \"lat\": -26.2044,\n    \"lng\": 28.0456,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"Gauteng\",\n    \"capital\": \"admin\",\n    \"population\": 8000000.0,\n    \"id\": 1710550792\n  },\n  {\n    \"city\": \"Soweto\",\n    \"city_ascii\": \"Soweto\",\n    \"lat\": -26.2678,\n    \"lng\": 27.8585,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"Gauteng\",\n    \"capital\": null,\n    \"population\": 1271628.0,\n    \"id\": 1710627007\n  },\n  {\n    \"city\": \"Cape Town\",\n    \"city_ascii\": \"Cape Town\",\n    \"lat\": -33.9253,\n    \"lng\": 18.4239,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"Western Cape\",\n    \"capital\": \"primary\",\n    \"population\": 433688.0,\n    \"id\": 1710680650\n  },\n  {\n    \"city\": \"Pietermaritzburg\",\n    \"city_ascii\": \"Pietermaritzburg\",\n    \"lat\": -29.6167,\n    \"lng\": 30.3833,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"KwaZulu-Natal\",\n    \"capital\": \"admin\",\n    \"population\": 750845.0,\n    \"id\": 1710690280\n  },\n  {\n    \"city\": \"Khayelitsha\",\n    \"city_ascii\": \"Khayelitsha\",\n    \"lat\": -34.0403,\n    \"lng\": 18.6778,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"Western Cape\",\n    \"capital\": null,\n    \"population\": 391749.0,\n    \"id\": 1710736316\n  },\n  {\n    \"city\": \"Katlehong\",\n    \"city_ascii\": \"Katlehong\",\n    \"lat\": -26.3333,\n    \"lng\": 28.15,\n    \"country\": \"South Africa\",\n    \"iso2\": \"ZA\",\n    \"iso3\": \"ZAF\",\n    \"admin_name\": \"Gauteng\",\n    \"capital\": null,\n    \"population\": 467890.0,\n    \"id\": 1710975690\n  },\n  {\n    \"city\": \"Bulawayo\",\n    \"city_ascii\": \"Bulawayo\",\n    \"lat\": -20.17,\n    \"lng\": 28.58,\n    \"country\": \"Zimbabwe\",\n    \"iso2\": \"ZW\",\n    \"iso3\": \"ZWE\",\n    \"admin_name\": \"Bulawayo\",\n    \"capital\": \"admin\",\n    \"population\": 653337.0,\n    \"id\": 1716032632\n  },\n  {\n    \"city\": \"Harare\",\n    \"city_ascii\": \"Harare\",\n    \"lat\": -17.8292,\n    \"lng\": 31.0522,\n    \"country\": \"Zimbabwe\",\n    \"iso2\": \"ZW\",\n    \"iso3\": \"ZWE\",\n    \"admin_name\": \"Harare\",\n    \"capital\": \"primary\",\n    \"population\": 2150000.0,\n    \"id\": 1716196799\n  },\n  {\n    \"city\": \"Chitungwiza\",\n    \"city_ascii\": \"Chitungwiza\",\n    \"lat\": -17.9939,\n    \"lng\": 31.0481,\n    \"country\": \"Zimbabwe\",\n    \"iso2\": \"ZW\",\n    \"iso3\": \"ZWE\",\n    \"admin_name\": \"Harare\",\n    \"capital\": null,\n    \"population\": 371244.0,\n    \"id\": 1716688236\n  },\n  {\n    \"city\": \"Murcia\",\n    \"city_ascii\": \"Murcia\",\n    \"lat\": 37.9861,\n    \"lng\": -1.1303,\n    \"country\": \"Spain\",\n    \"iso2\": \"ES\",\n    \"iso3\": \"ESP\",\n    \"admin_name\": \"Murcia\",\n    \"capital\": \"admin\",\n    \"population\": 672773.0,\n    \"id\": 1724107739\n  },\n  {\n    \"city\": \"Bilbao\",\n    \"city_ascii\": \"Bilbao\",\n    \"lat\": 43.2569,\n    \"lng\": -2.9236,\n    \"country\": \"Spain\",\n    \"iso2\": \"ES\",\n    \"iso3\": \"ESP\",\n    \"admin_name\": \"Basque Country\",\n    \"capital\": \"minor\",\n    \"population\": 775000.0,\n    \"id\": 1724331267\n  },\n  {\n    \"city\": \"Málaga\",\n    \"city_ascii\": \"Malaga\",\n    \"lat\": 36.7194,\n    \"lng\": -4.42,\n    \"country\": \"Spain\",\n    \"iso2\": \"ES\",\n    \"iso3\": \"ESP\",\n    \"admin_name\": \"Andalusia\",\n    \"capital\": \"minor\",\n    \"population\": 967250.0,\n    \"id\": 1724397372\n  },\n  {\n    \"city\": \"Las Palmas\",\n    \"city_ascii\": \"Las Palmas\",\n    \"lat\": 28.1272,\n    \"lng\": -15.4314,\n    \"country\": \"Spain\",\n    \"iso2\": \"ES\",\n    \"iso3\": \"ESP\",\n    \"admin_name\": \"Canary Islands\",\n    \"capital\": \"admin\",\n    \"population\": 378797.0,\n    \"id\": 1724501748\n  },\n  {\n    \"city\": \"Barcelona\",\n    \"city_ascii\": \"Barcelona\",\n    \"lat\": 41.3825,\n    \"lng\": 2.1769,\n    \"country\": \"Spain\",\n    \"iso2\": \"ES\",\n    \"iso3\": \"ESP\",\n    \"admin_name\": \"Catalonia\",\n    \"capital\": \"admin\",\n    \"population\": 4800000.0,\n    \"id\": 1724594040\n  },\n  {\n    \"city\": \"Madrid\",\n    \"city_ascii\": \"Madrid\",\n    \"lat\": 40.4169,\n    \"lng\": -3.7033,\n    \"country\": \"Spain\",\n    \"iso2\": \"ES\",\n    \"iso3\": \"ESP\",\n    \"admin_name\": \"Madrid\",\n    \"capital\": \"primary\",\n    \"population\": 6211000.0,\n    \"id\": 1724616994\n  },\n  {\n    \"city\": \"Palma\",\n    \"city_ascii\": \"Palma\",\n    \"lat\": 39.5667,\n    \"lng\": 2.65,\n    \"country\": \"Spain\",\n    \"iso2\": \"ES\",\n    \"iso3\": \"ESP\",\n    \"admin_name\": \"Balearic Islands\",\n    \"capital\": \"admin\",\n    \"population\": 550000.0,\n    \"id\": 1724728111\n  },\n  {\n    \"city\": \"Zaragoza\",\n    \"city_ascii\": \"Zaragoza\",\n    \"lat\": 41.65,\n    \"lng\": -0.8833,\n    \"country\": \"Spain\",\n    \"iso2\": \"ES\",\n    \"iso3\": \"ESP\",\n    \"admin_name\": \"Aragon\",\n    \"capital\": \"admin\",\n    \"population\": 675301.0,\n    \"id\": 1724907391\n  },\n  {\n    \"city\": \"Valencia\",\n    \"city_ascii\": \"Valencia\",\n    \"lat\": 39.47,\n    \"lng\": -0.3764,\n    \"country\": \"Spain\",\n    \"iso2\": \"ES\",\n    \"iso3\": \"ESP\",\n    \"admin_name\": \"Valencia\",\n    \"capital\": \"admin\",\n    \"population\": 792492.0,\n    \"id\": 1724981666\n  },\n  {\n    \"city\": \"Sevilla\",\n    \"city_ascii\": \"Sevilla\",\n    \"lat\": 37.24,\n    \"lng\": -5.99,\n    \"country\": \"Spain\",\n    \"iso2\": \"ES\",\n    \"iso3\": \"ESP\",\n    \"admin_name\": \"Andalusia\",\n    \"capital\": \"admin\",\n    \"population\": 1100000.0,\n    \"id\": 1724991838\n  },\n  {\n    \"city\": \"Juba\",\n    \"city_ascii\": \"Juba\",\n    \"lat\": 4.85,\n    \"lng\": 31.6,\n    \"country\": \"South Sudan\",\n    \"iso2\": \"SS\",\n    \"iso3\": \"SSD\",\n    \"admin_name\": \"Central Equatoria\",\n    \"capital\": \"primary\",\n    \"population\": 525953.0,\n    \"id\": 1728444337\n  },\n  {\n    \"city\": \"Kassala\",\n    \"city_ascii\": \"Kassala\",\n    \"lat\": 15.45,\n    \"lng\": 36.4,\n    \"country\": \"Sudan\",\n    \"iso2\": \"SD\",\n    \"iso3\": \"SDN\",\n    \"admin_name\": \"Kassala\",\n    \"capital\": \"admin\",\n    \"population\": 536009.0,\n    \"id\": 1729157224\n  },\n  {\n    \"city\": \"Gedaref\",\n    \"city_ascii\": \"Gedaref\",\n    \"lat\": 14.0333,\n    \"lng\": 35.3833,\n    \"country\": \"Sudan\",\n    \"iso2\": \"SD\",\n    \"iso3\": \"SDN\",\n    \"admin_name\": \"Gedaref\",\n    \"capital\": \"admin\",\n    \"population\": 354927.0,\n    \"id\": 1729215057\n  },\n  {\n    \"city\": \"El Obeid\",\n    \"city_ascii\": \"El Obeid\",\n    \"lat\": 13.1833,\n    \"lng\": 30.2167,\n    \"country\": \"Sudan\",\n    \"iso2\": \"SD\",\n    \"iso3\": \"SDN\",\n    \"admin_name\": \"North Kordofan\",\n    \"capital\": \"admin\",\n    \"population\": 418280.0,\n    \"id\": 1729215531\n  },\n  {\n    \"city\": \"Kūstī\",\n    \"city_ascii\": \"Kusti\",\n    \"lat\": 13.1667,\n    \"lng\": 32.6667,\n    \"country\": \"Sudan\",\n    \"iso2\": \"SD\",\n    \"iso3\": \"SDN\",\n    \"admin_name\": \"White Nile\",\n    \"capital\": null,\n    \"population\": 345068.0,\n    \"id\": 1729229371\n  },\n  {\n    \"city\": \"Khartoum\",\n    \"city_ascii\": \"Khartoum\",\n    \"lat\": 15.5006,\n    \"lng\": 32.56,\n    \"country\": \"Sudan\",\n    \"iso2\": \"SD\",\n    \"iso3\": \"SDN\",\n    \"admin_name\": \"Khartoum\",\n    \"capital\": \"primary\",\n    \"population\": 7869000.0,\n    \"id\": 1729268475\n  },\n  {\n    \"city\": \"Khartoum North\",\n    \"city_ascii\": \"Khartoum North\",\n    \"lat\": 15.6333,\n    \"lng\": 32.6333,\n    \"country\": \"Sudan\",\n    \"iso2\": \"SD\",\n    \"iso3\": \"SDN\",\n    \"admin_name\": \"Khartoum\",\n    \"capital\": null,\n    \"population\": 936349.0,\n    \"id\": 1729318628\n  },\n  {\n    \"city\": \"Wad Medani\",\n    \"city_ascii\": \"Wad Medani\",\n    \"lat\": 14.4,\n    \"lng\": 33.5167,\n    \"country\": \"Sudan\",\n    \"iso2\": \"SD\",\n    \"iso3\": \"SDN\",\n    \"admin_name\": \"Gezira\",\n    \"capital\": \"admin\",\n    \"population\": 345290.0,\n    \"id\": 1729581572\n  },\n  {\n    \"city\": \"Port Sudan\",\n    \"city_ascii\": \"Port Sudan\",\n    \"lat\": 19.6167,\n    \"lng\": 37.2167,\n    \"country\": \"Sudan\",\n    \"iso2\": \"SD\",\n    \"iso3\": \"SDN\",\n    \"admin_name\": \"Red Sea\",\n    \"capital\": \"admin\",\n    \"population\": 579942.0,\n    \"id\": 1729710259\n  },\n  {\n    \"city\": \"Al Mijlad\",\n    \"city_ascii\": \"Al Mijlad\",\n    \"lat\": 11.0339,\n    \"lng\": 27.74,\n    \"country\": \"Sudan\",\n    \"iso2\": \"SD\",\n    \"iso3\": \"SDN\",\n    \"admin_name\": \"West Kordofan\",\n    \"capital\": null,\n    \"population\": 985000.0,\n    \"id\": 1729768355\n  },\n  {\n    \"city\": \"Nyala\",\n    \"city_ascii\": \"Nyala\",\n    \"lat\": 12.05,\n    \"lng\": 24.8833,\n    \"country\": \"Sudan\",\n    \"iso2\": \"SD\",\n    \"iso3\": \"SDN\",\n    \"admin_name\": \"South Darfur\",\n    \"capital\": \"admin\",\n    \"population\": 492984.0,\n    \"id\": 1729833248\n  },\n  {\n    \"city\": \"Omdurman\",\n    \"city_ascii\": \"Omdurman\",\n    \"lat\": 15.65,\n    \"lng\": 32.4833,\n    \"country\": \"Sudan\",\n    \"iso2\": \"SD\",\n    \"iso3\": \"SDN\",\n    \"admin_name\": \"Khartoum\",\n    \"capital\": null,\n    \"population\": 2805396.0,\n    \"id\": 1729912179\n  },\n  {\n    \"city\": \"Gothenburg\",\n    \"city_ascii\": \"Gothenburg\",\n    \"lat\": 57.7075,\n    \"lng\": 11.9675,\n    \"country\": \"Sweden\",\n    \"iso2\": \"SE\",\n    \"iso3\": \"SWE\",\n    \"admin_name\": \"Västra Götaland\",\n    \"capital\": \"admin\",\n    \"population\": 607882.0,\n    \"id\": 1752059374\n  },\n  {\n    \"city\": \"Stockholm\",\n    \"city_ascii\": \"Stockholm\",\n    \"lat\": 59.3294,\n    \"lng\": 18.0686,\n    \"country\": \"Sweden\",\n    \"iso2\": \"SE\",\n    \"iso3\": \"SWE\",\n    \"admin_name\": \"Stockholm\",\n    \"capital\": \"primary\",\n    \"population\": 1611776.0,\n    \"id\": 1752425602\n  },\n  {\n    \"city\": \"Malmö\",\n    \"city_ascii\": \"Malmo\",\n    \"lat\": 55.6058,\n    \"lng\": 13.0358,\n    \"country\": \"Sweden\",\n    \"iso2\": \"SE\",\n    \"iso3\": \"SWE\",\n    \"admin_name\": \"Skåne\",\n    \"capital\": \"admin\",\n    \"population\": 351749.0,\n    \"id\": 1752705818\n  },\n  {\n    \"city\": \"Zürich\",\n    \"city_ascii\": \"Zurich\",\n    \"lat\": 47.3744,\n    \"lng\": 8.5411,\n    \"country\": \"Switzerland\",\n    \"iso2\": \"CH\",\n    \"iso3\": \"CHE\",\n    \"admin_name\": \"Zürich\",\n    \"capital\": \"admin\",\n    \"population\": 436332.0,\n    \"id\": 1756539143\n  },\n  {\n    \"city\": \"Homs\",\n    \"city_ascii\": \"Homs\",\n    \"lat\": 34.7333,\n    \"lng\": 36.7167,\n    \"country\": \"Syria\",\n    \"iso2\": \"SY\",\n    \"iso3\": \"SYR\",\n    \"admin_name\": \"Ḩimş\",\n    \"capital\": \"admin\",\n    \"population\": 775404.0,\n    \"id\": 1760013934\n  },\n  {\n    \"city\": \"Ḩamāh\",\n    \"city_ascii\": \"Hamah\",\n    \"lat\": 35.1333,\n    \"lng\": 36.75,\n    \"country\": \"Syria\",\n    \"iso2\": \"SY\",\n    \"iso3\": \"SYR\",\n    \"admin_name\": \"Ḩamāh\",\n    \"capital\": \"admin\",\n    \"population\": 696863.0,\n    \"id\": 1760197502\n  },\n  {\n    \"city\": \"Aleppo\",\n    \"city_ascii\": \"Aleppo\",\n    \"lat\": 36.2,\n    \"lng\": 37.16,\n    \"country\": \"Syria\",\n    \"iso2\": \"SY\",\n    \"iso3\": \"SYR\",\n    \"admin_name\": \"Ḩalab\",\n    \"capital\": \"admin\",\n    \"population\": 1916781.0,\n    \"id\": 1760366651\n  },\n  {\n    \"city\": \"Latakia\",\n    \"city_ascii\": \"Latakia\",\n    \"lat\": 35.5167,\n    \"lng\": 35.7833,\n    \"country\": \"Syria\",\n    \"iso2\": \"SY\",\n    \"iso3\": \"SYR\",\n    \"admin_name\": \"Al Lādhiqīyah\",\n    \"capital\": \"admin\",\n    \"population\": 700000.0,\n    \"id\": 1760555544\n  },\n  {\n    \"city\": \"Damascus\",\n    \"city_ascii\": \"Damascus\",\n    \"lat\": 33.5131,\n    \"lng\": 36.2919,\n    \"country\": \"Syria\",\n    \"iso2\": \"SY\",\n    \"iso3\": \"SYR\",\n    \"admin_name\": \"Dimashq\",\n    \"capital\": \"primary\",\n    \"population\": 1754000.0,\n    \"id\": 1760685964\n  },\n  {\n    \"city\": \"Khŭjand\",\n    \"city_ascii\": \"Khujand\",\n    \"lat\": 40.2833,\n    \"lng\": 69.6333,\n    \"country\": \"Tajikistan\",\n    \"iso2\": \"TJ\",\n    \"iso3\": \"TJK\",\n    \"admin_name\": \"Sughd\",\n    \"capital\": \"admin\",\n    \"population\": 770000.0,\n    \"id\": 1762372787\n  },\n  {\n    \"city\": \"Dushanbe\",\n    \"city_ascii\": \"Dushanbe\",\n    \"lat\": 38.5367,\n    \"lng\": 68.78,\n    \"country\": \"Tajikistan\",\n    \"iso2\": \"TJ\",\n    \"iso3\": \"TJK\",\n    \"admin_name\": \"Dushanbe\",\n    \"capital\": \"primary\",\n    \"population\": 863400.0,\n    \"id\": 1762930616\n  },\n  {\n    \"city\": \"Bangkok\",\n    \"city_ascii\": \"Bangkok\",\n    \"lat\": 13.7525,\n    \"lng\": 100.4942,\n    \"country\": \"Thailand\",\n    \"iso2\": \"TH\",\n    \"iso3\": \"THA\",\n    \"admin_name\": \"Krung Thep Maha Nakhon\",\n    \"capital\": \"primary\",\n    \"population\": 18007000.0,\n    \"id\": 1764068610\n  },\n  {\n    \"city\": \"Chiang Mai\",\n    \"city_ascii\": \"Chiang Mai\",\n    \"lat\": 18.7953,\n    \"lng\": 98.9986,\n    \"country\": \"Thailand\",\n    \"iso2\": \"TH\",\n    \"iso3\": \"THA\",\n    \"admin_name\": \"Chiang Mai\",\n    \"capital\": \"admin\",\n    \"population\": 1198000.0,\n    \"id\": 1764662886\n  },\n  {\n    \"city\": \"Lomé\",\n    \"city_ascii\": \"Lome\",\n    \"lat\": 6.1319,\n    \"lng\": 1.2228,\n    \"country\": \"Togo\",\n    \"iso2\": \"TG\",\n    \"iso3\": \"TGO\",\n    \"admin_name\": \"Maritime\",\n    \"capital\": \"primary\",\n    \"population\": 837437.0,\n    \"id\": 1768409132\n  },\n  {\n    \"city\": \"Sharjah\",\n    \"city_ascii\": \"Sharjah\",\n    \"lat\": 25.3575,\n    \"lng\": 55.3908,\n    \"country\": \"United Arab Emirates\",\n    \"iso2\": \"AE\",\n    \"iso3\": \"ARE\",\n    \"admin_name\": \"Ash Shāriqah\",\n    \"capital\": \"admin\",\n    \"population\": 1247749.0,\n    \"id\": 1784152993\n  },\n  {\n    \"city\": \"Abu Dhabi\",\n    \"city_ascii\": \"Abu Dhabi\",\n    \"lat\": 24.4667,\n    \"lng\": 54.3667,\n    \"country\": \"United Arab Emirates\",\n    \"iso2\": \"AE\",\n    \"iso3\": \"ARE\",\n    \"admin_name\": \"Abū Z̧aby\",\n    \"capital\": \"primary\",\n    \"population\": 1483000.0,\n    \"id\": 1784176710\n  },\n  {\n    \"city\": \"‘Ajmān\",\n    \"city_ascii\": \"`Ajman\",\n    \"lat\": 25.4136,\n    \"lng\": 55.4456,\n    \"country\": \"United Arab Emirates\",\n    \"iso2\": \"AE\",\n    \"iso3\": \"ARE\",\n    \"admin_name\": \"‘Ajmān\",\n    \"capital\": \"admin\",\n    \"population\": 490035.0,\n    \"id\": 1784337875\n  },\n  {\n    \"city\": \"Al ‘Ayn\",\n    \"city_ascii\": \"Al `Ayn\",\n    \"lat\": 24.2075,\n    \"lng\": 55.7447,\n    \"country\": \"United Arab Emirates\",\n    \"iso2\": \"AE\",\n    \"iso3\": \"ARE\",\n    \"admin_name\": \"Abū Z̧aby\",\n    \"capital\": null,\n    \"population\": 766936.0,\n    \"id\": 1784674685\n  },\n  {\n    \"city\": \"Dubai\",\n    \"city_ascii\": \"Dubai\",\n    \"lat\": 25.2631,\n    \"lng\": 55.2972,\n    \"country\": \"United Arab Emirates\",\n    \"iso2\": \"AE\",\n    \"iso3\": \"ARE\",\n    \"admin_name\": \"Dubayy\",\n    \"capital\": \"admin\",\n    \"population\": 3331420.0,\n    \"id\": 1784736618\n  },\n  {\n    \"city\": \"Sidi Bouzid\",\n    \"city_ascii\": \"Sidi Bouzid\",\n    \"lat\": 35.0381,\n    \"lng\": 9.4858,\n    \"country\": \"Tunisia\",\n    \"iso2\": \"TN\",\n    \"iso3\": \"TUN\",\n    \"admin_name\": \"Sidi Bouzid\",\n    \"capital\": \"admin\",\n    \"population\": 429912.0,\n    \"id\": 1788196439\n  },\n  {\n    \"city\": \"Tunis\",\n    \"city_ascii\": \"Tunis\",\n    \"lat\": 36.8064,\n    \"lng\": 10.1817,\n    \"country\": \"Tunisia\",\n    \"iso2\": \"TN\",\n    \"iso3\": \"TUN\",\n    \"admin_name\": \"Tunis\",\n    \"capital\": \"primary\",\n    \"population\": 1056247.0,\n    \"id\": 1788742103\n  },\n  {\n    \"city\": \"Esenler\",\n    \"city_ascii\": \"Esenler\",\n    \"lat\": 41.0339,\n    \"lng\": 28.8903,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İstanbul\",\n    \"capital\": null,\n    \"population\": 444561.0,\n    \"id\": 1792000667\n  },\n  {\n    \"city\": \"Konya\",\n    \"city_ascii\": \"Konya\",\n    \"lat\": 37.8667,\n    \"lng\": 32.4833,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Konya\",\n    \"capital\": \"admin\",\n    \"population\": 2232374.0,\n    \"id\": 1792014004\n  },\n  {\n    \"city\": \"Trabzon\",\n    \"city_ascii\": \"Trabzon\",\n    \"lat\": 41.005,\n    \"lng\": 39.7225,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Trabzon\",\n    \"capital\": \"admin\",\n    \"population\": 426882.0,\n    \"id\": 1792019202\n  },\n  {\n    \"city\": \"Hatay\",\n    \"city_ascii\": \"Hatay\",\n    \"lat\": 36.2025,\n    \"lng\": 36.1606,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Hatay\",\n    \"capital\": \"admin\",\n    \"population\": 377793.0,\n    \"id\": 1792115763\n  },\n  {\n    \"city\": \"Avcılar\",\n    \"city_ascii\": \"Avcilar\",\n    \"lat\": 40.9792,\n    \"lng\": 28.7214,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İstanbul\",\n    \"capital\": null,\n    \"population\": 435625.0,\n    \"id\": 1792144759\n  },\n  {\n    \"city\": \"Elazığ\",\n    \"city_ascii\": \"Elazig\",\n    \"lat\": 38.6744,\n    \"lng\": 39.2228,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Elazığ\",\n    \"capital\": \"admin\",\n    \"population\": 421726.0,\n    \"id\": 1792156766\n  },\n  {\n    \"city\": \"Denizli\",\n    \"city_ascii\": \"Denizli\",\n    \"lat\": 37.7667,\n    \"lng\": 29.0833,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Denizli\",\n    \"capital\": \"admin\",\n    \"population\": 1027782.0,\n    \"id\": 1792161179\n  },\n  {\n    \"city\": \"Samsun\",\n    \"city_ascii\": \"Samsun\",\n    \"lat\": 41.2903,\n    \"lng\": 36.3336,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Samsun\",\n    \"capital\": \"admin\",\n    \"population\": 1335716.0,\n    \"id\": 1792169057\n  },\n  {\n    \"city\": \"Yüreğir\",\n    \"city_ascii\": \"Yuregir\",\n    \"lat\": 36.9981,\n    \"lng\": 35.3439,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Adana\",\n    \"capital\": \"minor\",\n    \"population\": 407054.0,\n    \"id\": 1792234391\n  },\n  {\n    \"city\": \"Bağcılar\",\n    \"city_ascii\": \"Bagcilar\",\n    \"lat\": 41.0344,\n    \"lng\": 28.8564,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İstanbul\",\n    \"capital\": null,\n    \"population\": 734369.0,\n    \"id\": 1792374908\n  },\n  {\n    \"city\": \"Sarıyer\",\n    \"city_ascii\": \"Sariyer\",\n    \"lat\": 41.1669,\n    \"lng\": 29.0572,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İstanbul\",\n    \"capital\": \"minor\",\n    \"population\": 342503.0,\n    \"id\": 1792425356\n  },\n  {\n    \"city\": \"Çankaya\",\n    \"city_ascii\": \"Cankaya\",\n    \"lat\": 39.9244,\n    \"lng\": 32.8856,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Ankara\",\n    \"capital\": \"minor\",\n    \"population\": 914501.0,\n    \"id\": 1792458894\n  },\n  {\n    \"city\": \"Malatya\",\n    \"city_ascii\": \"Malatya\",\n    \"lat\": 38.3486,\n    \"lng\": 38.3194,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Malatya\",\n    \"capital\": \"admin\",\n    \"population\": 426381.0,\n    \"id\": 1792485155\n  },\n  {\n    \"city\": \"Erzurum\",\n    \"city_ascii\": \"Erzurum\",\n    \"lat\": 39.9086,\n    \"lng\": 41.2769,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Erzurum\",\n    \"capital\": \"admin\",\n    \"population\": 767848.0,\n    \"id\": 1792511957\n  },\n  {\n    \"city\": \"Mersin\",\n    \"city_ascii\": \"Mersin\",\n    \"lat\": 36.8,\n    \"lng\": 34.6333,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Mersin\",\n    \"capital\": \"admin\",\n    \"population\": 1814468.0,\n    \"id\": 1792520282\n  },\n  {\n    \"city\": \"Kâğıthane\",\n    \"city_ascii\": \"Kagithane\",\n    \"lat\": 41.0719,\n    \"lng\": 28.9664,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İstanbul\",\n    \"capital\": null,\n    \"population\": 437026.0,\n    \"id\": 1792526380\n  },\n  {\n    \"city\": \"Diyarbakır\",\n    \"city_ascii\": \"Diyarbakir\",\n    \"lat\": 37.91,\n    \"lng\": 40.24,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Diyarbakır\",\n    \"capital\": \"admin\",\n    \"population\": 1732396.0,\n    \"id\": 1792536241\n  },\n  {\n    \"city\": \"Akçaabat\",\n    \"city_ascii\": \"Akcaabat\",\n    \"lat\": 41.0167,\n    \"lng\": 39.55,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Trabzon\",\n    \"capital\": \"minor\",\n    \"population\": 1215351.0,\n    \"id\": 1792536331\n  },\n  {\n    \"city\": \"Ankara\",\n    \"city_ascii\": \"Ankara\",\n    \"lat\": 39.93,\n    \"lng\": 32.85,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Ankara\",\n    \"capital\": \"primary\",\n    \"population\": 5503985.0,\n    \"id\": 1792572891\n  },\n  {\n    \"city\": \"Batman\",\n    \"city_ascii\": \"Batman\",\n    \"lat\": 37.887,\n    \"lng\": 41.132,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Batman\",\n    \"capital\": \"admin\",\n    \"population\": 447106.0,\n    \"id\": 1792630786\n  },\n  {\n    \"city\": \"Gebze\",\n    \"city_ascii\": \"Gebze\",\n    \"lat\": 40.8,\n    \"lng\": 29.4333,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Kocaeli\",\n    \"capital\": \"minor\",\n    \"population\": 371000.0,\n    \"id\": 1792650082\n  },\n  {\n    \"city\": \"Seyhan\",\n    \"city_ascii\": \"Seyhan\",\n    \"lat\": 36.9831,\n    \"lng\": 35.3328,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Adana\",\n    \"capital\": \"minor\",\n    \"population\": 792536.0,\n    \"id\": 1792655353\n  },\n  {\n    \"city\": \"Konak\",\n    \"city_ascii\": \"Konak\",\n    \"lat\": 38.4189,\n    \"lng\": 27.1285,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İzmir\",\n    \"capital\": \"minor\",\n    \"population\": 356563.0,\n    \"id\": 1792668647\n  },\n  {\n    \"city\": \"Selçuklu\",\n    \"city_ascii\": \"Selcuklu\",\n    \"lat\": 37.8814,\n    \"lng\": 32.4922,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Konya\",\n    \"capital\": \"minor\",\n    \"population\": 648850.0,\n    \"id\": 1792683478\n  },\n  {\n    \"city\": \"İzmir\",\n    \"city_ascii\": \"Izmir\",\n    \"lat\": 38.42,\n    \"lng\": 27.14,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İzmir\",\n    \"capital\": \"admin\",\n    \"population\": 4320519.0,\n    \"id\": 1792725579\n  },\n  {\n    \"city\": \"Kahramanmaraş\",\n    \"city_ascii\": \"Kahramanmaras\",\n    \"lat\": 37.5833,\n    \"lng\": 36.9333,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Kahramanmaraş\",\n    \"capital\": \"admin\",\n    \"population\": 443575.0,\n    \"id\": 1792726797\n  },\n  {\n    \"city\": \"Pamukkale\",\n    \"city_ascii\": \"Pamukkale\",\n    \"lat\": 37.9167,\n    \"lng\": 29.1167,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Denizli\",\n    \"capital\": null,\n    \"population\": 346625.0,\n    \"id\": 1792749284\n  },\n  {\n    \"city\": \"Istanbul\",\n    \"city_ascii\": \"Istanbul\",\n    \"lat\": 41.0136,\n    \"lng\": 28.955,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İstanbul\",\n    \"capital\": \"admin\",\n    \"population\": 16079000.0,\n    \"id\": 1792756324\n  },\n  {\n    \"city\": \"Esenyurt\",\n    \"city_ascii\": \"Esenyurt\",\n    \"lat\": 41.047,\n    \"lng\": 28.658,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İstanbul\",\n    \"capital\": null,\n    \"population\": 891120.0,\n    \"id\": 1792759121\n  },\n  {\n    \"city\": \"Yıldırım\",\n    \"city_ascii\": \"Yildirim\",\n    \"lat\": 40.11,\n    \"lng\": 29.0821,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Bursa\",\n    \"capital\": \"minor\",\n    \"population\": 643681.0,\n    \"id\": 1792764051\n  },\n  {\n    \"city\": \"Adana\",\n    \"city_ascii\": \"Adana\",\n    \"lat\": 37.0,\n    \"lng\": 35.3213,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Adana\",\n    \"capital\": \"admin\",\n    \"population\": 1765981.0,\n    \"id\": 1792783772\n  },\n  {\n    \"city\": \"Manisa\",\n    \"city_ascii\": \"Manisa\",\n    \"lat\": 38.6306,\n    \"lng\": 27.4222,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Manisa\",\n    \"capital\": \"admin\",\n    \"population\": 356702.0,\n    \"id\": 1792804328\n  },\n  {\n    \"city\": \"Pendik\",\n    \"city_ascii\": \"Pendik\",\n    \"lat\": 40.8747,\n    \"lng\": 29.235,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İstanbul\",\n    \"capital\": \"minor\",\n    \"population\": 693599.0,\n    \"id\": 1792824929\n  },\n  {\n    \"city\": \"Meram\",\n    \"city_ascii\": \"Meram\",\n    \"lat\": 37.8364,\n    \"lng\": 32.4383,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Konya\",\n    \"capital\": \"minor\",\n    \"population\": 342315.0,\n    \"id\": 1792895883\n  },\n  {\n    \"city\": \"Bursa\",\n    \"city_ascii\": \"Bursa\",\n    \"lat\": 40.1833,\n    \"lng\": 29.05,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Bursa\",\n    \"capital\": \"admin\",\n    \"population\": 2901396.0,\n    \"id\": 1792903330\n  },\n  {\n    \"city\": \"Kayapınar\",\n    \"city_ascii\": \"Kayapinar\",\n    \"lat\": 37.94,\n    \"lng\": 40.19,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Diyarbakır\",\n    \"capital\": \"minor\",\n    \"population\": 362407.0,\n    \"id\": 1792910994\n  },\n  {\n    \"city\": \"Gaziantep\",\n    \"city_ascii\": \"Gaziantep\",\n    \"lat\": 37.0628,\n    \"lng\": 37.3792,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Gaziantep\",\n    \"capital\": \"admin\",\n    \"population\": 2028563.0,\n    \"id\": 1792911843\n  },\n  {\n    \"city\": \"Eskişehir\",\n    \"city_ascii\": \"Eskisehir\",\n    \"lat\": 39.7767,\n    \"lng\": 30.5206,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Eskişehir\",\n    \"capital\": \"admin\",\n    \"population\": 871187.0,\n    \"id\": 1792933981\n  },\n  {\n    \"city\": \"Şanlıurfa\",\n    \"city_ascii\": \"Sanliurfa\",\n    \"lat\": 37.1583,\n    \"lng\": 38.7917,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Şanlıurfa\",\n    \"capital\": \"admin\",\n    \"population\": 1985753.0,\n    \"id\": 1792937570\n  },\n  {\n    \"city\": \"Sivas\",\n    \"city_ascii\": \"Sivas\",\n    \"lat\": 39.75,\n    \"lng\": 37.0167,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Sivas\",\n    \"capital\": \"admin\",\n    \"population\": 377561.0,\n    \"id\": 1792938326\n  },\n  {\n    \"city\": \"Van\",\n    \"city_ascii\": \"Van\",\n    \"lat\": 38.4942,\n    \"lng\": 43.38,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Van\",\n    \"capital\": \"admin\",\n    \"population\": 353419.0,\n    \"id\": 1792940471\n  },\n  {\n    \"city\": \"Kayseri\",\n    \"city_ascii\": \"Kayseri\",\n    \"lat\": 38.7225,\n    \"lng\": 35.4875,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Kayseri\",\n    \"capital\": \"admin\",\n    \"population\": 1389680.0,\n    \"id\": 1792945815\n  },\n  {\n    \"city\": \"Kocaeli\",\n    \"city_ascii\": \"Kocaeli\",\n    \"lat\": 40.7625,\n    \"lng\": 29.9175,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Kocaeli\",\n    \"capital\": \"admin\",\n    \"population\": 363416.0,\n    \"id\": 1792965114\n  },\n  {\n    \"city\": \"Antalya\",\n    \"city_ascii\": \"Antalya\",\n    \"lat\": 36.8874,\n    \"lng\": 30.7075,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"Antalya\",\n    \"capital\": \"admin\",\n    \"population\": 2426356.0,\n    \"id\": 1792988434\n  },\n  {\n    \"city\": \"Kartal\",\n    \"city_ascii\": \"Kartal\",\n    \"lat\": 40.8872,\n    \"lng\": 29.19,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İstanbul\",\n    \"capital\": \"minor\",\n    \"population\": 461155.0,\n    \"id\": 1792988658\n  },\n  {\n    \"city\": \"Küçükçekmece\",\n    \"city_ascii\": \"Kucukcekmece\",\n    \"lat\": 41.0,\n    \"lng\": 28.8,\n    \"country\": \"Turkey\",\n    \"iso2\": \"TR\",\n    \"iso3\": \"TUR\",\n    \"admin_name\": \"İstanbul\",\n    \"capital\": \"minor\",\n    \"population\": 770317.0,\n    \"id\": 1792992349\n  },\n  {\n    \"city\": \"Ashgabat\",\n    \"city_ascii\": \"Ashgabat\",\n    \"lat\": 37.95,\n    \"lng\": 58.3833,\n    \"country\": \"Turkmenistan\",\n    \"iso2\": \"TM\",\n    \"iso3\": \"TKM\",\n    \"admin_name\": \"Aşgabat\",\n    \"capital\": \"primary\",\n    \"population\": 828100.0,\n    \"id\": 1795049992\n  },\n  {\n    \"city\": \"Türkmenabat\",\n    \"city_ascii\": \"Turkmenabat\",\n    \"lat\": 39.0833,\n    \"lng\": 63.5667,\n    \"country\": \"Turkmenistan\",\n    \"iso2\": \"TM\",\n    \"iso3\": \"TKM\",\n    \"admin_name\": \"Lebap\",\n    \"capital\": \"admin\",\n    \"population\": 408906.0,\n    \"id\": 1795079064\n  },\n  {\n    \"city\": \"Nansana\",\n    \"city_ascii\": \"Nansana\",\n    \"lat\": 0.3639,\n    \"lng\": 32.5286,\n    \"country\": \"Uganda\",\n    \"iso2\": \"UG\",\n    \"iso3\": \"UGA\",\n    \"admin_name\": \"Wakiso\",\n    \"capital\": null,\n    \"population\": 532800.0,\n    \"id\": 1800032516\n  },\n  {\n    \"city\": \"Mbale\",\n    \"city_ascii\": \"Mbale\",\n    \"lat\": 1.0806,\n    \"lng\": 34.175,\n    \"country\": \"Uganda\",\n    \"iso2\": \"UG\",\n    \"iso3\": \"UGA\",\n    \"admin_name\": \"Mbale\",\n    \"capital\": \"admin\",\n    \"population\": 586300.0,\n    \"id\": 1800265900\n  },\n  {\n    \"city\": \"Kampala\",\n    \"city_ascii\": \"Kampala\",\n    \"lat\": 0.3136,\n    \"lng\": 32.5811,\n    \"country\": \"Uganda\",\n    \"iso2\": \"UG\",\n    \"iso3\": \"UGA\",\n    \"admin_name\": \"Kampala\",\n    \"capital\": \"primary\",\n    \"population\": 1680600.0,\n    \"id\": 1800406299\n  },\n  {\n    \"city\": \"Dnipro\",\n    \"city_ascii\": \"Dnipro\",\n    \"lat\": 48.4675,\n    \"lng\": 35.04,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Dnipropetrovska Oblast\",\n    \"capital\": \"admin\",\n    \"population\": 980948.0,\n    \"id\": 1804152933\n  },\n  {\n    \"city\": \"Odesa\",\n    \"city_ascii\": \"Odesa\",\n    \"lat\": 46.4775,\n    \"lng\": 30.7326,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Odeska Oblast\",\n    \"capital\": \"admin\",\n    \"population\": 1017699.0,\n    \"id\": 1804178102\n  },\n  {\n    \"city\": \"Kyiv\",\n    \"city_ascii\": \"Kyiv\",\n    \"lat\": 50.45,\n    \"lng\": 30.5233,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Kyiv, Misto\",\n    \"capital\": \"primary\",\n    \"population\": 2963199.0,\n    \"id\": 1804382913\n  },\n  {\n    \"city\": \"Mykolaiv\",\n    \"city_ascii\": \"Mykolaiv\",\n    \"lat\": 46.975,\n    \"lng\": 31.995,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Mykolaivska Oblast\",\n    \"capital\": \"admin\",\n    \"population\": 498748.0,\n    \"id\": 1804398395\n  },\n  {\n    \"city\": \"Kryvyi Rih\",\n    \"city_ascii\": \"Kryvyi Rih\",\n    \"lat\": 47.9086,\n    \"lng\": 33.3433,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Dnipropetrovska Oblast\",\n    \"capital\": \"minor\",\n    \"population\": 629695.0,\n    \"id\": 1804544901\n  },\n  {\n    \"city\": \"Kharkiv\",\n    \"city_ascii\": \"Kharkiv\",\n    \"lat\": 49.9925,\n    \"lng\": 36.2311,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Kharkivska Oblast\",\n    \"capital\": \"admin\",\n    \"population\": 1446107.0,\n    \"id\": 1804588111\n  },\n  {\n    \"city\": \"Mariupol\",\n    \"city_ascii\": \"Mariupol\",\n    \"lat\": 47.0958,\n    \"lng\": 37.5494,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Donetska Oblast\",\n    \"capital\": \"minor\",\n    \"population\": 449498.0,\n    \"id\": 1804630021\n  },\n  {\n    \"city\": \"Zaporizhzhia\",\n    \"city_ascii\": \"Zaporizhzhia\",\n    \"lat\": 47.85,\n    \"lng\": 35.1175,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Zaporizka Oblast\",\n    \"capital\": \"admin\",\n    \"population\": 741717.0,\n    \"id\": 1804644752\n  },\n  {\n    \"city\": \"Vinnytsia\",\n    \"city_ascii\": \"Vinnytsia\",\n    \"lat\": 49.2333,\n    \"lng\": 28.4833,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Vinnytska Oblast\",\n    \"capital\": \"admin\",\n    \"population\": 371855.0,\n    \"id\": 1804658571\n  },\n  {\n    \"city\": \"Simferopol\",\n    \"city_ascii\": \"Simferopol\",\n    \"lat\": 44.9484,\n    \"lng\": 34.1,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Krym, Avtonomna Respublika\",\n    \"capital\": \"admin\",\n    \"population\": 341799.0,\n    \"id\": 1804665958\n  },\n  {\n    \"city\": \"Luhansk\",\n    \"city_ascii\": \"Luhansk\",\n    \"lat\": 48.5667,\n    \"lng\": 39.3333,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Luhanska Oblast\",\n    \"capital\": \"admin\",\n    \"population\": 417990.0,\n    \"id\": 1804688214\n  },\n  {\n    \"city\": \"Sevastopol\",\n    \"city_ascii\": \"Sevastopol\",\n    \"lat\": 44.605,\n    \"lng\": 33.5225,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Sevastopol, Misto\",\n    \"capital\": \"admin\",\n    \"population\": 522057.0,\n    \"id\": 1804806030\n  },\n  {\n    \"city\": \"Makiivka\",\n    \"city_ascii\": \"Makiivka\",\n    \"lat\": 48.0556,\n    \"lng\": 37.9611,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Donetska Oblast\",\n    \"capital\": \"minor\",\n    \"population\": 343158.0,\n    \"id\": 1804926154\n  },\n  {\n    \"city\": \"Lviv\",\n    \"city_ascii\": \"Lviv\",\n    \"lat\": 49.8425,\n    \"lng\": 24.0322,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Lvivska Oblast\",\n    \"capital\": \"admin\",\n    \"population\": 724314.0,\n    \"id\": 1804939658\n  },\n  {\n    \"city\": \"Donetsk\",\n    \"city_ascii\": \"Donetsk\",\n    \"lat\": 48.0028,\n    \"lng\": 37.8053,\n    \"country\": \"Ukraine\",\n    \"iso2\": \"UA\",\n    \"iso3\": \"UKR\",\n    \"admin_name\": \"Donetska Oblast\",\n    \"capital\": \"admin\",\n    \"population\": 929063.0,\n    \"id\": 1804963805\n  },\n  {\n    \"city\": \"Skopje\",\n    \"city_ascii\": \"Skopje\",\n    \"lat\": 41.9961,\n    \"lng\": 21.4317,\n    \"country\": \"Macedonia\",\n    \"iso2\": \"MK\",\n    \"iso3\": \"MKD\",\n    \"admin_name\": \"Skopje\",\n    \"capital\": \"primary\",\n    \"population\": 640000.0,\n    \"id\": 1807600615\n  },\n  {\n    \"city\": \"Ḩalwān\",\n    \"city_ascii\": \"Halwan\",\n    \"lat\": 29.8453,\n    \"lng\": 31.3333,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Al Qāhirah\",\n    \"capital\": null,\n    \"population\": 619293.0,\n    \"id\": 1818000039\n  },\n  {\n    \"city\": \"Cairo\",\n    \"city_ascii\": \"Cairo\",\n    \"lat\": 30.0444,\n    \"lng\": 31.2358,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Al Qāhirah\",\n    \"capital\": \"primary\",\n    \"population\": 20296000.0,\n    \"id\": 1818253931\n  },\n  {\n    \"city\": \"Al Manşūrah\",\n    \"city_ascii\": \"Al Mansurah\",\n    \"lat\": 31.05,\n    \"lng\": 31.3833,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Ad Daqahlīyah\",\n    \"capital\": \"admin\",\n    \"population\": 960423.0,\n    \"id\": 1818255319\n  },\n  {\n    \"city\": \"Al ‘Āshir min Ramaḑān\",\n    \"city_ascii\": \"Al `Ashir min Ramadan\",\n    \"lat\": 30.3065,\n    \"lng\": 31.7415,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Ash Sharqīyah\",\n    \"capital\": null,\n    \"population\": 511987.0,\n    \"id\": 1818297014\n  },\n  {\n    \"city\": \"Al Maḩallah al Kubrá\",\n    \"city_ascii\": \"Al Mahallah al Kubra\",\n    \"lat\": 30.9686,\n    \"lng\": 31.1636,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Al Gharbīyah\",\n    \"capital\": null,\n    \"population\": 535278.0,\n    \"id\": 1818406471\n  },\n  {\n    \"city\": \"Asyūţ\",\n    \"city_ascii\": \"Asyut\",\n    \"lat\": 27.1833,\n    \"lng\": 31.1667,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Asyūţ\",\n    \"capital\": \"admin\",\n    \"population\": 389307.0,\n    \"id\": 1818456592\n  },\n  {\n    \"city\": \"Suez\",\n    \"city_ascii\": \"Suez\",\n    \"lat\": 29.9667,\n    \"lng\": 32.55,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"As Suways\",\n    \"capital\": \"admin\",\n    \"population\": 516959.0,\n    \"id\": 1818495972\n  },\n  {\n    \"city\": \"Ţanţā\",\n    \"city_ascii\": \"Tanta\",\n    \"lat\": 30.7833,\n    \"lng\": 31.0,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Al Gharbīyah\",\n    \"capital\": \"admin\",\n    \"population\": 429503.0,\n    \"id\": 1818501770\n  },\n  {\n    \"city\": \"Port Said\",\n    \"city_ascii\": \"Port Said\",\n    \"lat\": 31.2625,\n    \"lng\": 32.3061,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Būr Sa‘īd\",\n    \"capital\": \"admin\",\n    \"population\": 524433.0,\n    \"id\": 1818628574\n  },\n  {\n    \"city\": \"Alexandria\",\n    \"city_ascii\": \"Alexandria\",\n    \"lat\": 31.1975,\n    \"lng\": 29.8925,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Al Iskandarīyah\",\n    \"capital\": \"admin\",\n    \"population\": 4870000.0,\n    \"id\": 1818695837\n  },\n  {\n    \"city\": \"Ash Shuhadā’\",\n    \"city_ascii\": \"Ash Shuhada'\",\n    \"lat\": 30.6039,\n    \"lng\": 30.9021,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Al Minūfīyah\",\n    \"capital\": null,\n    \"population\": 358486.0,\n    \"id\": 1818906012\n  },\n  {\n    \"city\": \"Shubrā al Khaymah\",\n    \"city_ascii\": \"Shubra al Khaymah\",\n    \"lat\": 30.1286,\n    \"lng\": 31.2422,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Al Qalyūbīyah\",\n    \"capital\": null,\n    \"population\": 1025569.0,\n    \"id\": 1818909612\n  },\n  {\n    \"city\": \"Giza\",\n    \"city_ascii\": \"Giza\",\n    \"lat\": 29.987,\n    \"lng\": 31.2118,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Al Jīzah\",\n    \"capital\": \"admin\",\n    \"population\": 5598402.0,\n    \"id\": 1818925479\n  },\n  {\n    \"city\": \"Bibā\",\n    \"city_ascii\": \"Biba\",\n    \"lat\": 28.9218,\n    \"lng\": 30.9844,\n    \"country\": \"Egypt\",\n    \"iso2\": \"EG\",\n    \"iso3\": \"EGY\",\n    \"admin_name\": \"Banī Suwayf\",\n    \"capital\": null,\n    \"population\": 385528.0,\n    \"id\": 1818994454\n  },\n  {\n    \"city\": \"Nottingham\",\n    \"city_ascii\": \"Nottingham\",\n    \"lat\": 52.9533,\n    \"lng\": -1.15,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Nottingham\",\n    \"capital\": null,\n    \"population\": 768638.0,\n    \"id\": 1826122597\n  },\n  {\n    \"city\": \"Manchester\",\n    \"city_ascii\": \"Manchester\",\n    \"lat\": 53.4794,\n    \"lng\": -2.2453,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Manchester\",\n    \"capital\": null,\n    \"population\": 2705000.0,\n    \"id\": 1826246335\n  },\n  {\n    \"city\": \"Sheffield\",\n    \"city_ascii\": \"Sheffield\",\n    \"lat\": 53.3808,\n    \"lng\": -1.4703,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Sheffield\",\n    \"capital\": null,\n    \"population\": 518090.0,\n    \"id\": 1826289852\n  },\n  {\n    \"city\": \"Leeds\",\n    \"city_ascii\": \"Leeds\",\n    \"lat\": 53.8003,\n    \"lng\": -1.5497,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Leeds\",\n    \"capital\": null,\n    \"population\": 789194.0,\n    \"id\": 1826343963\n  },\n  {\n    \"city\": \"Caerdydd\",\n    \"city_ascii\": \"Caerdydd\",\n    \"lat\": 51.4817,\n    \"lng\": -3.1792,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Cardiff\",\n    \"capital\": null,\n    \"population\": 479000.0,\n    \"id\": 1826362422\n  },\n  {\n    \"city\": \"Birmingham\",\n    \"city_ascii\": \"Birmingham\",\n    \"lat\": 52.48,\n    \"lng\": -1.9025,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Birmingham\",\n    \"capital\": null,\n    \"population\": 2919600.0,\n    \"id\": 1826423213\n  },\n  {\n    \"city\": \"Leicester\",\n    \"city_ascii\": \"Leicester\",\n    \"lat\": 52.6344,\n    \"lng\": -1.1319,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Leicester\",\n    \"capital\": null,\n    \"population\": 508916.0,\n    \"id\": 1826431946\n  },\n  {\n    \"city\": \"Edinburgh\",\n    \"city_ascii\": \"Edinburgh\",\n    \"lat\": 55.9533,\n    \"lng\": -3.1892,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Edinburgh, City of\",\n    \"capital\": null,\n    \"population\": 488050.0,\n    \"id\": 1826492520\n  },\n  {\n    \"city\": \"Liverpool\",\n    \"city_ascii\": \"Liverpool\",\n    \"lat\": 53.4075,\n    \"lng\": -2.9919,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Liverpool\",\n    \"capital\": null,\n    \"population\": 864122.0,\n    \"id\": 1826558678\n  },\n  {\n    \"city\": \"Southampton\",\n    \"city_ascii\": \"Southampton\",\n    \"lat\": 50.9025,\n    \"lng\": -1.4042,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Southampton\",\n    \"capital\": null,\n    \"population\": 855569.0,\n    \"id\": 1826602892\n  },\n  {\n    \"city\": \"London\",\n    \"city_ascii\": \"London\",\n    \"lat\": 51.5072,\n    \"lng\": -0.1275,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"London, City of\",\n    \"capital\": \"primary\",\n    \"population\": 11262000.0,\n    \"id\": 1826645935\n  },\n  {\n    \"city\": \"Stoke-on-Trent\",\n    \"city_ascii\": \"Stoke-on-Trent\",\n    \"lat\": 53.0,\n    \"lng\": -2.1833,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Stoke-on-Trent\",\n    \"capital\": null,\n    \"population\": 372775.0,\n    \"id\": 1826799578\n  },\n  {\n    \"city\": \"Glasgow\",\n    \"city_ascii\": \"Glasgow\",\n    \"lat\": 55.8611,\n    \"lng\": -4.25,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Glasgow City\",\n    \"capital\": null,\n    \"population\": 626410.0,\n    \"id\": 1826836462\n  },\n  {\n    \"city\": \"Bristol\",\n    \"city_ascii\": \"Bristol\",\n    \"lat\": 51.4536,\n    \"lng\": -2.5975,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Bristol, City of\",\n    \"capital\": null,\n    \"population\": 567111.0,\n    \"id\": 1826921049\n  },\n  {\n    \"city\": \"Worthing\",\n    \"city_ascii\": \"Worthing\",\n    \"lat\": 50.8147,\n    \"lng\": -0.3714,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"West Sussex\",\n    \"capital\": null,\n    \"population\": 474485.0,\n    \"id\": 1826936965\n  },\n  {\n    \"city\": \"Portsmouth\",\n    \"city_ascii\": \"Portsmouth\",\n    \"lat\": 50.8058,\n    \"lng\": -1.0872,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Portsmouth\",\n    \"capital\": null,\n    \"population\": 855679.0,\n    \"id\": 1826964096\n  },\n  {\n    \"city\": \"Coventry\",\n    \"city_ascii\": \"Coventry\",\n    \"lat\": 52.4081,\n    \"lng\": -1.5106,\n    \"country\": \"United Kingdom\",\n    \"iso2\": \"GB\",\n    \"iso3\": \"GBR\",\n    \"admin_name\": \"Coventry\",\n    \"capital\": null,\n    \"population\": 362690.0,\n    \"id\": 1826979198\n  },\n  {\n    \"city\": \"Mwanza\",\n    \"city_ascii\": \"Mwanza\",\n    \"lat\": -2.5167,\n    \"lng\": 32.9,\n    \"country\": \"Tanzania\",\n    \"iso2\": \"TZ\",\n    \"iso3\": \"TZA\",\n    \"admin_name\": \"Mwanza\",\n    \"capital\": \"admin\",\n    \"population\": 706453.0,\n    \"id\": 1834011288\n  },\n  {\n    \"city\": \"Mbeya\",\n    \"city_ascii\": \"Mbeya\",\n    \"lat\": -8.9,\n    \"lng\": 33.45,\n    \"country\": \"Tanzania\",\n    \"iso2\": \"TZ\",\n    \"iso3\": \"TZA\",\n    \"admin_name\": \"Mbeya\",\n    \"capital\": \"admin\",\n    \"population\": 467000.0,\n    \"id\": 1834396594\n  },\n  {\n    \"city\": \"Arusha\",\n    \"city_ascii\": \"Arusha\",\n    \"lat\": -3.3667,\n    \"lng\": 36.6833,\n    \"country\": \"Tanzania\",\n    \"iso2\": \"TZ\",\n    \"iso3\": \"TZA\",\n    \"admin_name\": \"Arusha\",\n    \"capital\": \"admin\",\n    \"population\": 416442.0,\n    \"id\": 1834484937\n  },\n  {\n    \"city\": \"Dar es Salaam\",\n    \"city_ascii\": \"Dar es Salaam\",\n    \"lat\": -6.8161,\n    \"lng\": 39.2803,\n    \"country\": \"Tanzania\",\n    \"iso2\": \"TZ\",\n    \"iso3\": \"TZA\",\n    \"admin_name\": \"Dar es Salaam\",\n    \"capital\": \"primary\",\n    \"population\": 7962000.0,\n    \"id\": 1834843853\n  },\n  {\n    \"city\": \"Rochester\",\n    \"city_ascii\": \"Rochester\",\n    \"lat\": 43.168,\n    \"lng\": -77.6162,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 737309.0,\n    \"id\": 1840000373\n  },\n  {\n    \"city\": \"Syracuse\",\n    \"city_ascii\": \"Syracuse\",\n    \"lat\": 43.0407,\n    \"lng\": -76.1437,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 418875.0,\n    \"id\": 1840000378\n  },\n  {\n    \"city\": \"Buffalo\",\n    \"city_ascii\": \"Buffalo\",\n    \"lat\": 42.9018,\n    \"lng\": -78.8487,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 1004655.0,\n    \"id\": 1840000386\n  },\n  {\n    \"city\": \"Albany\",\n    \"city_ascii\": \"Albany\",\n    \"lat\": 42.6664,\n    \"lng\": -73.7987,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": \"admin\",\n    \"population\": 604077.0,\n    \"id\": 1840000417\n  },\n  {\n    \"city\": \"Worcester\",\n    \"city_ascii\": \"Worcester\",\n    \"lat\": 42.2705,\n    \"lng\": -71.8079,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Massachusetts\",\n    \"capital\": null,\n    \"population\": 573573.0,\n    \"id\": 1840000434\n  },\n  {\n    \"city\": \"Boston\",\n    \"city_ascii\": \"Boston\",\n    \"lat\": 42.3188,\n    \"lng\": -71.0852,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Massachusetts\",\n    \"capital\": \"admin\",\n    \"population\": 4208580.0,\n    \"id\": 1840000455\n  },\n  {\n    \"city\": \"Springfield\",\n    \"city_ascii\": \"Springfield\",\n    \"lat\": 42.1155,\n    \"lng\": -72.5395,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Massachusetts\",\n    \"capital\": null,\n    \"population\": 620494.0,\n    \"id\": 1840000466\n  },\n  {\n    \"city\": \"Chicago\",\n    \"city_ascii\": \"Chicago\",\n    \"lat\": 41.8375,\n    \"lng\": -87.6866,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Illinois\",\n    \"capital\": null,\n    \"population\": 8595181.0,\n    \"id\": 1840000494\n  },\n  {\n    \"city\": \"Poughkeepsie\",\n    \"city_ascii\": \"Poughkeepsie\",\n    \"lat\": 41.695,\n    \"lng\": -73.9211,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 423386.0,\n    \"id\": 1840000500\n  },\n  {\n    \"city\": \"Toledo\",\n    \"city_ascii\": \"Toledo\",\n    \"lat\": 41.6638,\n    \"lng\": -83.5827,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Ohio\",\n    \"capital\": null,\n    \"population\": 490832.0,\n    \"id\": 1840000572\n  },\n  {\n    \"city\": \"Cleveland\",\n    \"city_ascii\": \"Cleveland\",\n    \"lat\": 41.4764,\n    \"lng\": -81.6805,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Ohio\",\n    \"capital\": null,\n    \"population\": 1683059.0,\n    \"id\": 1840000596\n  },\n  {\n    \"city\": \"Philadelphia\",\n    \"city_ascii\": \"Philadelphia\",\n    \"lat\": 40.0077,\n    \"lng\": -75.1339,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Pennsylvania\",\n    \"capital\": null,\n    \"population\": 5512873.0,\n    \"id\": 1840000673\n  },\n  {\n    \"city\": \"Akron\",\n    \"city_ascii\": \"Akron\",\n    \"lat\": 41.0798,\n    \"lng\": -81.5219,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Ohio\",\n    \"capital\": null,\n    \"population\": 546549.0,\n    \"id\": 1840000791\n  },\n  {\n    \"city\": \"Allentown\",\n    \"city_ascii\": \"Allentown\",\n    \"lat\": 40.5961,\n    \"lng\": -75.4756,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Pennsylvania\",\n    \"capital\": null,\n    \"population\": 714136.0,\n    \"id\": 1840001044\n  },\n  {\n    \"city\": \"Pittsburgh\",\n    \"city_ascii\": \"Pittsburgh\",\n    \"lat\": 40.4397,\n    \"lng\": -79.9763,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Pennsylvania\",\n    \"capital\": null,\n    \"population\": 1720279.0,\n    \"id\": 1840001254\n  },\n  {\n    \"city\": \"Harrisburg\",\n    \"city_ascii\": \"Harrisburg\",\n    \"lat\": 40.2752,\n    \"lng\": -76.8843,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Pennsylvania\",\n    \"capital\": \"admin\",\n    \"population\": 472261.0,\n    \"id\": 1840001288\n  },\n  {\n    \"city\": \"Baltimore\",\n    \"city_ascii\": \"Baltimore\",\n    \"lat\": 39.3051,\n    \"lng\": -76.6144,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Maryland\",\n    \"capital\": null,\n    \"population\": 2205092.0,\n    \"id\": 1840001592\n  },\n  {\n    \"city\": \"St. Louis\",\n    \"city_ascii\": \"St. Louis\",\n    \"lat\": 38.6359,\n    \"lng\": -90.2451,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Missouri\",\n    \"capital\": null,\n    \"population\": 2092481.0,\n    \"id\": 1840001651\n  },\n  {\n    \"city\": \"Wichita\",\n    \"city_ascii\": \"Wichita\",\n    \"lat\": 37.6895,\n    \"lng\": -97.3443,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Kansas\",\n    \"capital\": null,\n    \"population\": 491916.0,\n    \"id\": 1840001686\n  },\n  {\n    \"city\": \"Richmond\",\n    \"city_ascii\": \"Richmond\",\n    \"lat\": 37.5295,\n    \"lng\": -77.4756,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Virginia\",\n    \"capital\": \"admin\",\n    \"population\": 1008069.0,\n    \"id\": 1840001698\n  },\n  {\n    \"city\": \"New Orleans\",\n    \"city_ascii\": \"New Orleans\",\n    \"lat\": 30.0687,\n    \"lng\": -89.9288,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Louisiana\",\n    \"capital\": null,\n    \"population\": 925443.0,\n    \"id\": 1840001839\n  },\n  {\n    \"city\": \"Madison\",\n    \"city_ascii\": \"Madison\",\n    \"lat\": 43.0822,\n    \"lng\": -89.393,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Wisconsin\",\n    \"capital\": \"admin\",\n    \"population\": 461778.0,\n    \"id\": 1840002915\n  },\n  {\n    \"city\": \"Grand Rapids\",\n    \"city_ascii\": \"Grand Rapids\",\n    \"lat\": 42.9619,\n    \"lng\": -85.6562,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Michigan\",\n    \"capital\": null,\n    \"population\": 604311.0,\n    \"id\": 1840002928\n  },\n  {\n    \"city\": \"Milwaukee\",\n    \"city_ascii\": \"Milwaukee\",\n    \"lat\": 43.0642,\n    \"lng\": -87.9675,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Wisconsin\",\n    \"capital\": null,\n    \"population\": 1340981.0,\n    \"id\": 1840003046\n  },\n  {\n    \"city\": \"Providence\",\n    \"city_ascii\": \"Providence\",\n    \"lat\": 41.823,\n    \"lng\": -71.4187,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Rhode Island\",\n    \"capital\": \"admin\",\n    \"population\": 1270149.0,\n    \"id\": 1840003289\n  },\n  {\n    \"city\": \"Scranton\",\n    \"city_ascii\": \"Scranton\",\n    \"lat\": 41.4044,\n    \"lng\": -75.6649,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Pennsylvania\",\n    \"capital\": null,\n    \"population\": 376974.0,\n    \"id\": 1840003389\n  },\n  {\n    \"city\": \"Youngstown\",\n    \"city_ascii\": \"Youngstown\",\n    \"lat\": 41.0993,\n    \"lng\": -80.6463,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Ohio\",\n    \"capital\": null,\n    \"population\": 363541.0,\n    \"id\": 1840003563\n  },\n  {\n    \"city\": \"Lancaster\",\n    \"city_ascii\": \"Lancaster\",\n    \"lat\": 40.042,\n    \"lng\": -76.3012,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Pennsylvania\",\n    \"capital\": null,\n    \"population\": 430621.0,\n    \"id\": 1840003718\n  },\n  {\n    \"city\": \"Columbus\",\n    \"city_ascii\": \"Columbus\",\n    \"lat\": 39.9862,\n    \"lng\": -82.9855,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Ohio\",\n    \"capital\": \"admin\",\n    \"population\": 1556848.0,\n    \"id\": 1840003760\n  },\n  {\n    \"city\": \"Cincinnati\",\n    \"city_ascii\": \"Cincinnati\",\n    \"lat\": 39.1413,\n    \"lng\": -84.506,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Ohio\",\n    \"capital\": null,\n    \"population\": 1712287.0,\n    \"id\": 1840003814\n  },\n  {\n    \"city\": \"Virginia Beach\",\n    \"city_ascii\": \"Virginia Beach\",\n    \"lat\": 36.7335,\n    \"lng\": -76.0435,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Virginia\",\n    \"capital\": null,\n    \"population\": 1500764.0,\n    \"id\": 1840003871\n  },\n  {\n    \"city\": \"Detroit\",\n    \"city_ascii\": \"Detroit\",\n    \"lat\": 42.3834,\n    \"lng\": -83.1024,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Michigan\",\n    \"capital\": null,\n    \"population\": 3522856.0,\n    \"id\": 1840003971\n  },\n  {\n    \"city\": \"Hartford\",\n    \"city_ascii\": \"Hartford\",\n    \"lat\": 41.7661,\n    \"lng\": -72.6834,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Connecticut\",\n    \"capital\": \"admin\",\n    \"population\": 907046.0,\n    \"id\": 1840004773\n  },\n  {\n    \"city\": \"Bridgeport\",\n    \"city_ascii\": \"Bridgeport\",\n    \"lat\": 41.1918,\n    \"lng\": -73.1954,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Connecticut\",\n    \"capital\": null,\n    \"population\": 975078.0,\n    \"id\": 1840004836\n  },\n  {\n    \"city\": \"New Haven\",\n    \"city_ascii\": \"New Haven\",\n    \"lat\": 41.3113,\n    \"lng\": -72.9246,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Connecticut\",\n    \"capital\": null,\n    \"population\": 587648.0,\n    \"id\": 1840004850\n  },\n  {\n    \"city\": \"Hempstead\",\n    \"city_ascii\": \"Hempstead\",\n    \"lat\": 40.6629,\n    \"lng\": -73.6089,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 791018.0,\n    \"id\": 1840005293\n  },\n  {\n    \"city\": \"Washington\",\n    \"city_ascii\": \"Washington\",\n    \"lat\": 38.9047,\n    \"lng\": -77.0163,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"District of Columbia\",\n    \"capital\": \"primary\",\n    \"population\": 4810669.0,\n    \"id\": 1840006060\n  },\n  {\n    \"city\": \"Birmingham\",\n    \"city_ascii\": \"Birmingham\",\n    \"lat\": 33.5279,\n    \"lng\": -86.7971,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Alabama\",\n    \"capital\": null,\n    \"population\": 704676.0,\n    \"id\": 1840006507\n  },\n  {\n    \"city\": \"Des Moines\",\n    \"city_ascii\": \"Des Moines\",\n    \"lat\": 41.5725,\n    \"lng\": -93.6105,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Iowa\",\n    \"capital\": \"admin\",\n    \"population\": 514654.0,\n    \"id\": 1840007069\n  },\n  {\n    \"city\": \"Minneapolis\",\n    \"city_ascii\": \"Minneapolis\",\n    \"lat\": 44.9635,\n    \"lng\": -93.2678,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Minnesota\",\n    \"capital\": null,\n    \"population\": 2856952.0,\n    \"id\": 1840007830\n  },\n  {\n    \"city\": \"Kansas City\",\n    \"city_ascii\": \"Kansas City\",\n    \"lat\": 39.1238,\n    \"lng\": -94.5541,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Missouri\",\n    \"capital\": null,\n    \"population\": 1644497.0,\n    \"id\": 1840008535\n  },\n  {\n    \"city\": \"Omaha\",\n    \"city_ascii\": \"Omaha\",\n    \"lat\": 41.2627,\n    \"lng\": -96.0529,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Nebraska\",\n    \"capital\": null,\n    \"population\": 806485.0,\n    \"id\": 1840009315\n  },\n  {\n    \"city\": \"Honolulu\",\n    \"city_ascii\": \"Honolulu\",\n    \"lat\": 21.3294,\n    \"lng\": -157.846,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Hawaii\",\n    \"capital\": \"admin\",\n    \"population\": 835291.0,\n    \"id\": 1840013305\n  },\n  {\n    \"city\": \"Greensboro\",\n    \"city_ascii\": \"Greensboro\",\n    \"lat\": 36.0956,\n    \"lng\": -79.8271,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"North Carolina\",\n    \"capital\": null,\n    \"population\": 345270.0,\n    \"id\": 1840013356\n  },\n  {\n    \"city\": \"Durham\",\n    \"city_ascii\": \"Durham\",\n    \"lat\": 35.9792,\n    \"lng\": -78.9022,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"North Carolina\",\n    \"capital\": null,\n    \"population\": 399762.0,\n    \"id\": 1840013364\n  },\n  {\n    \"city\": \"Fayetteville\",\n    \"city_ascii\": \"Fayetteville\",\n    \"lat\": 36.0714,\n    \"lng\": -94.1661,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Arkansas\",\n    \"capital\": null,\n    \"population\": 381636.0,\n    \"id\": 1840013368\n  },\n  {\n    \"city\": \"Greenville\",\n    \"city_ascii\": \"Greenville\",\n    \"lat\": 34.8354,\n    \"lng\": -82.3646,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"South Carolina\",\n    \"capital\": null,\n    \"population\": 450487.0,\n    \"id\": 1840013501\n  },\n  {\n    \"city\": \"Atlanta\",\n    \"city_ascii\": \"Atlanta\",\n    \"lat\": 33.7628,\n    \"lng\": -84.422,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Georgia\",\n    \"capital\": \"admin\",\n    \"population\": 5046555.0,\n    \"id\": 1840013660\n  },\n  {\n    \"city\": \"Baton Rouge\",\n    \"city_ascii\": \"Baton Rouge\",\n    \"lat\": 30.442,\n    \"lng\": -91.1311,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Louisiana\",\n    \"capital\": \"admin\",\n    \"population\": 610751.0,\n    \"id\": 1840013941\n  },\n  {\n    \"city\": \"Bonita Springs\",\n    \"city_ascii\": \"Bonita Springs\",\n    \"lat\": 26.3558,\n    \"lng\": -81.7859,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 347581.0,\n    \"id\": 1840014227\n  },\n  {\n    \"city\": \"Knoxville\",\n    \"city_ascii\": \"Knoxville\",\n    \"lat\": 35.9692,\n    \"lng\": -83.9496,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Tennessee\",\n    \"capital\": null,\n    \"population\": 619925.0,\n    \"id\": 1840014486\n  },\n  {\n    \"city\": \"Raleigh\",\n    \"city_ascii\": \"Raleigh\",\n    \"lat\": 35.8324,\n    \"lng\": -78.6429,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"North Carolina\",\n    \"capital\": \"admin\",\n    \"population\": 1062018.0,\n    \"id\": 1840014497\n  },\n  {\n    \"city\": \"Charlotte\",\n    \"city_ascii\": \"Charlotte\",\n    \"lat\": 35.2083,\n    \"lng\": -80.8303,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"North Carolina\",\n    \"capital\": null,\n    \"population\": 1516107.0,\n    \"id\": 1840014557\n  },\n  {\n    \"city\": \"Chattanooga\",\n    \"city_ascii\": \"Chattanooga\",\n    \"lat\": 35.066,\n    \"lng\": -85.2481,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Tennessee\",\n    \"capital\": null,\n    \"population\": 403233.0,\n    \"id\": 1840014569\n  },\n  {\n    \"city\": \"Columbia\",\n    \"city_ascii\": \"Columbia\",\n    \"lat\": 34.0378,\n    \"lng\": -80.9036,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"South Carolina\",\n    \"capital\": \"admin\",\n    \"population\": 640502.0,\n    \"id\": 1840014730\n  },\n  {\n    \"city\": \"Pensacola\",\n    \"city_ascii\": \"Pensacola\",\n    \"lat\": 30.4413,\n    \"lng\": -87.1911,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 360711.0,\n    \"id\": 1840015005\n  },\n  {\n    \"city\": \"Jacksonville\",\n    \"city_ascii\": \"Jacksonville\",\n    \"lat\": 30.3322,\n    \"lng\": -81.6749,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 1220191.0,\n    \"id\": 1840015031\n  },\n  {\n    \"city\": \"Palm Coast\",\n    \"city_ascii\": \"Palm Coast\",\n    \"lat\": 29.5389,\n    \"lng\": -81.2457,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 403834.0,\n    \"id\": 1840015064\n  },\n  {\n    \"city\": \"Palm Bay\",\n    \"city_ascii\": \"Palm Bay\",\n    \"lat\": 27.9631,\n    \"lng\": -80.6593,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 528322.0,\n    \"id\": 1840015094\n  },\n  {\n    \"city\": \"Orlando\",\n    \"city_ascii\": \"Orlando\",\n    \"lat\": 28.4773,\n    \"lng\": -81.337,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 1927699.0,\n    \"id\": 1840015099\n  },\n  {\n    \"city\": \"Kissimmee\",\n    \"city_ascii\": \"Kissimmee\",\n    \"lat\": 28.3041,\n    \"lng\": -81.4169,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 399929.0,\n    \"id\": 1840015109\n  },\n  {\n    \"city\": \"Port St. Lucie\",\n    \"city_ascii\": \"Port St. Lucie\",\n    \"lat\": 27.2796,\n    \"lng\": -80.3884,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 468979.0,\n    \"id\": 1840015119\n  },\n  {\n    \"city\": \"Cape Coral\",\n    \"city_ascii\": \"Cape Coral\",\n    \"lat\": 26.6443,\n    \"lng\": -81.9957,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 682773.0,\n    \"id\": 1840015130\n  },\n  {\n    \"city\": \"Miami\",\n    \"city_ascii\": \"Miami\",\n    \"lat\": 25.784,\n    \"lng\": -80.2101,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 5711945.0,\n    \"id\": 1840015149\n  },\n  {\n    \"city\": \"Charleston\",\n    \"city_ascii\": \"Charleston\",\n    \"lat\": 32.8168,\n    \"lng\": -79.9687,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"South Carolina\",\n    \"capital\": null,\n    \"population\": 685517.0,\n    \"id\": 1840015163\n  },\n  {\n    \"city\": \"Winston-Salem\",\n    \"city_ascii\": \"Winston-Salem\",\n    \"lat\": 36.1029,\n    \"lng\": -80.261,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"North Carolina\",\n    \"capital\": null,\n    \"population\": 420400.0,\n    \"id\": 1840015324\n  },\n  {\n    \"city\": \"Memphis\",\n    \"city_ascii\": \"Memphis\",\n    \"lat\": 35.1087,\n    \"lng\": -89.9663,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Tennessee\",\n    \"capital\": null,\n    \"population\": 1034498.0,\n    \"id\": 1840015457\n  },\n  {\n    \"city\": \"Little Rock\",\n    \"city_ascii\": \"Little Rock\",\n    \"lat\": 34.7256,\n    \"lng\": -92.3577,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Arkansas\",\n    \"capital\": \"admin\",\n    \"population\": 457379.0,\n    \"id\": 1840015509\n  },\n  {\n    \"city\": \"Tampa\",\n    \"city_ascii\": \"Tampa\",\n    \"lat\": 27.9945,\n    \"lng\": -82.4447,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 2683956.0,\n    \"id\": 1840015982\n  },\n  {\n    \"city\": \"Sarasota\",\n    \"city_ascii\": \"Sarasota\",\n    \"lat\": 27.3387,\n    \"lng\": -82.5432,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Florida\",\n    \"capital\": null,\n    \"population\": 727388.0,\n    \"id\": 1840015988\n  },\n  {\n    \"city\": \"Denver\",\n    \"city_ascii\": \"Denver\",\n    \"lat\": 39.762,\n    \"lng\": -104.8758,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Colorado\",\n    \"capital\": \"admin\",\n    \"population\": 2650725.0,\n    \"id\": 1840018789\n  },\n  {\n    \"city\": \"Aurora\",\n    \"city_ascii\": \"Aurora\",\n    \"lat\": 39.7083,\n    \"lng\": -104.7237,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Colorado\",\n    \"capital\": null,\n    \"population\": 383496.0,\n    \"id\": 1840018794\n  },\n  {\n    \"city\": \"Colorado Springs\",\n    \"city_ascii\": \"Colorado Springs\",\n    \"lat\": 38.8674,\n    \"lng\": -104.7605,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Colorado\",\n    \"capital\": null,\n    \"population\": 628808.0,\n    \"id\": 1840018825\n  },\n  {\n    \"city\": \"Concord\",\n    \"city_ascii\": \"Concord\",\n    \"lat\": 37.9722,\n    \"lng\": -122.0016,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 640270.0,\n    \"id\": 1840018905\n  },\n  {\n    \"city\": \"Bakersfield\",\n    \"city_ascii\": \"Bakersfield\",\n    \"lat\": 35.3529,\n    \"lng\": -119.0359,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 590845.0,\n    \"id\": 1840019148\n  },\n  {\n    \"city\": \"Albuquerque\",\n    \"city_ascii\": \"Albuquerque\",\n    \"lat\": 35.1054,\n    \"lng\": -106.6465,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New Mexico\",\n    \"capital\": null,\n    \"population\": 765693.0,\n    \"id\": 1840019176\n  },\n  {\n    \"city\": \"Indio\",\n    \"city_ascii\": \"Indio\",\n    \"lat\": 33.7346,\n    \"lng\": -116.2346,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 361831.0,\n    \"id\": 1840019304\n  },\n  {\n    \"city\": \"Anaheim\",\n    \"city_ascii\": \"Anaheim\",\n    \"lat\": 33.839,\n    \"lng\": -117.8574,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 348204.0,\n    \"id\": 1840019322\n  },\n  {\n    \"city\": \"Denton\",\n    \"city_ascii\": \"Denton\",\n    \"lat\": 33.2175,\n    \"lng\": -97.1418,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Texas\",\n    \"capital\": null,\n    \"population\": 445814.0,\n    \"id\": 1840019390\n  },\n  {\n    \"city\": \"Arlington\",\n    \"city_ascii\": \"Arlington\",\n    \"lat\": 32.6998,\n    \"lng\": -97.125,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Texas\",\n    \"capital\": null,\n    \"population\": 392304.0,\n    \"id\": 1840019422\n  },\n  {\n    \"city\": \"Dallas\",\n    \"city_ascii\": \"Dallas\",\n    \"lat\": 32.7935,\n    \"lng\": -96.7667,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Texas\",\n    \"capital\": null,\n    \"population\": 5668165.0,\n    \"id\": 1840019440\n  },\n  {\n    \"city\": \"Austin\",\n    \"city_ascii\": \"Austin\",\n    \"lat\": 30.3005,\n    \"lng\": -97.7522,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Texas\",\n    \"capital\": \"admin\",\n    \"population\": 1659251.0,\n    \"id\": 1840019590\n  },\n  {\n    \"city\": \"Portland\",\n    \"city_ascii\": \"Portland\",\n    \"lat\": 45.5371,\n    \"lng\": -122.65,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Oregon\",\n    \"capital\": null,\n    \"population\": 2036875.0,\n    \"id\": 1840019941\n  },\n  {\n    \"city\": \"Reno\",\n    \"city_ascii\": \"Reno\",\n    \"lat\": 39.5497,\n    \"lng\": -119.8483,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Nevada\",\n    \"capital\": null,\n    \"population\": 463328.0,\n    \"id\": 1840020121\n  },\n  {\n    \"city\": \"Ogden\",\n    \"city_ascii\": \"Ogden\",\n    \"lat\": 41.2279,\n    \"lng\": -111.9682,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Utah\",\n    \"capital\": null,\n    \"population\": 608259.0,\n    \"id\": 1840020135\n  },\n  {\n    \"city\": \"Provo\",\n    \"city_ascii\": \"Provo\",\n    \"lat\": 40.2457,\n    \"lng\": -111.6457,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Utah\",\n    \"capital\": null,\n    \"population\": 551645.0,\n    \"id\": 1840020174\n  },\n  {\n    \"city\": \"Modesto\",\n    \"city_ascii\": \"Modesto\",\n    \"lat\": 37.6375,\n    \"lng\": -121.0028,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 382994.0,\n    \"id\": 1840020287\n  },\n  {\n    \"city\": \"Oakland\",\n    \"city_ascii\": \"Oakland\",\n    \"lat\": 37.7904,\n    \"lng\": -122.2166,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 437548.0,\n    \"id\": 1840020296\n  },\n  {\n    \"city\": \"Fresno\",\n    \"city_ascii\": \"Fresno\",\n    \"lat\": 36.783,\n    \"lng\": -119.7939,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 719558.0,\n    \"id\": 1840020319\n  },\n  {\n    \"city\": \"Las Vegas\",\n    \"city_ascii\": \"Las Vegas\",\n    \"lat\": 36.2333,\n    \"lng\": -115.2654,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Nevada\",\n    \"capital\": null,\n    \"population\": 2150373.0,\n    \"id\": 1840020364\n  },\n  {\n    \"city\": \"Oklahoma City\",\n    \"city_ascii\": \"Oklahoma City\",\n    \"lat\": 35.4676,\n    \"lng\": -97.5136,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Oklahoma\",\n    \"capital\": \"admin\",\n    \"population\": 994284.0,\n    \"id\": 1840020428\n  },\n  {\n    \"city\": \"Oxnard\",\n    \"city_ascii\": \"Oxnard\",\n    \"lat\": 34.1964,\n    \"lng\": -119.1815,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 366330.0,\n    \"id\": 1840020474\n  },\n  {\n    \"city\": \"Long Beach\",\n    \"city_ascii\": \"Long Beach\",\n    \"lat\": 33.7977,\n    \"lng\": -118.167,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 466565.0,\n    \"id\": 1840020490\n  },\n  {\n    \"city\": \"Los Angeles\",\n    \"city_ascii\": \"Los Angeles\",\n    \"lat\": 34.1141,\n    \"lng\": -118.4068,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 12121244.0,\n    \"id\": 1840020491\n  },\n  {\n    \"city\": \"Lancaster\",\n    \"city_ascii\": \"Lancaster\",\n    \"lat\": 34.6935,\n    \"lng\": -118.1753,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 381732.0,\n    \"id\": 1840020516\n  },\n  {\n    \"city\": \"Riverside\",\n    \"city_ascii\": \"Riverside\",\n    \"lat\": 33.9381,\n    \"lng\": -117.3949,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 2022285.0,\n    \"id\": 1840020551\n  },\n  {\n    \"city\": \"Murrieta\",\n    \"city_ascii\": \"Murrieta\",\n    \"lat\": 33.5719,\n    \"lng\": -117.1909,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 509526.0,\n    \"id\": 1840020553\n  },\n  {\n    \"city\": \"Mesa\",\n    \"city_ascii\": \"Mesa\",\n    \"lat\": 33.4015,\n    \"lng\": -111.7178,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Arizona\",\n    \"capital\": null,\n    \"population\": 497752.0,\n    \"id\": 1840020566\n  },\n  {\n    \"city\": \"Phoenix\",\n    \"city_ascii\": \"Phoenix\",\n    \"lat\": 33.5722,\n    \"lng\": -112.0892,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Arizona\",\n    \"capital\": \"admin\",\n    \"population\": 4047095.0,\n    \"id\": 1840020568\n  },\n  {\n    \"city\": \"Mission Viejo\",\n    \"city_ascii\": \"Mission Viejo\",\n    \"lat\": 33.6096,\n    \"lng\": -117.6551,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 588540.0,\n    \"id\": 1840020580\n  },\n  {\n    \"city\": \"Fort Worth\",\n    \"city_ascii\": \"Fort Worth\",\n    \"lat\": 32.7817,\n    \"lng\": -97.3474,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Texas\",\n    \"capital\": null,\n    \"population\": 908469.0,\n    \"id\": 1840020696\n  },\n  {\n    \"city\": \"Houston\",\n    \"city_ascii\": \"Houston\",\n    \"lat\": 29.786,\n    \"lng\": -95.3885,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Texas\",\n    \"capital\": null,\n    \"population\": 5650910.0,\n    \"id\": 1840020925\n  },\n  {\n    \"city\": \"McAllen\",\n    \"city_ascii\": \"McAllen\",\n    \"lat\": 26.2252,\n    \"lng\": -98.2467,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Texas\",\n    \"capital\": null,\n    \"population\": 809002.0,\n    \"id\": 1840021024\n  },\n  {\n    \"city\": \"Spokane\",\n    \"city_ascii\": \"Spokane\",\n    \"lat\": 47.6671,\n    \"lng\": -117.433,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Washington\",\n    \"capital\": null,\n    \"population\": 440270.0,\n    \"id\": 1840021093\n  },\n  {\n    \"city\": \"Seattle\",\n    \"city_ascii\": \"Seattle\",\n    \"lat\": 47.6211,\n    \"lng\": -122.3244,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Washington\",\n    \"capital\": null,\n    \"population\": 3438221.0,\n    \"id\": 1840021117\n  },\n  {\n    \"city\": \"Salt Lake City\",\n    \"city_ascii\": \"Salt Lake City\",\n    \"lat\": 40.7776,\n    \"lng\": -111.9311,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Utah\",\n    \"capital\": \"admin\",\n    \"population\": 1135344.0,\n    \"id\": 1840021383\n  },\n  {\n    \"city\": \"Sacramento\",\n    \"city_ascii\": \"Sacramento\",\n    \"lat\": 38.5677,\n    \"lng\": -121.4685,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": \"admin\",\n    \"population\": 1924167.0,\n    \"id\": 1840021491\n  },\n  {\n    \"city\": \"Stockton\",\n    \"city_ascii\": \"Stockton\",\n    \"lat\": 37.9765,\n    \"lng\": -121.3109,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 406822.0,\n    \"id\": 1840021517\n  },\n  {\n    \"city\": \"San Francisco\",\n    \"city_ascii\": \"San Francisco\",\n    \"lat\": 37.7558,\n    \"lng\": -122.4449,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 3290197.0,\n    \"id\": 1840021543\n  },\n  {\n    \"city\": \"San Jose\",\n    \"city_ascii\": \"San Jose\",\n    \"lat\": 37.3012,\n    \"lng\": -121.848,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 1729879.0,\n    \"id\": 1840021570\n  },\n  {\n    \"city\": \"Tulsa\",\n    \"city_ascii\": \"Tulsa\",\n    \"lat\": 36.1283,\n    \"lng\": -95.9042,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Oklahoma\",\n    \"capital\": null,\n    \"population\": 715983.0,\n    \"id\": 1840021672\n  },\n  {\n    \"city\": \"Victorville\",\n    \"city_ascii\": \"Victorville\",\n    \"lat\": 34.5277,\n    \"lng\": -117.3536,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 389060.0,\n    \"id\": 1840021731\n  },\n  {\n    \"city\": \"San Diego\",\n    \"city_ascii\": \"San Diego\",\n    \"lat\": 32.8313,\n    \"lng\": -117.1222,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"California\",\n    \"capital\": null,\n    \"population\": 3084174.0,\n    \"id\": 1840021990\n  },\n  {\n    \"city\": \"Tucson\",\n    \"city_ascii\": \"Tucson\",\n    \"lat\": 32.1541,\n    \"lng\": -110.8787,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Arizona\",\n    \"capital\": null,\n    \"population\": 875284.0,\n    \"id\": 1840022101\n  },\n  {\n    \"city\": \"San Antonio\",\n    \"city_ascii\": \"San Antonio\",\n    \"lat\": 29.4632,\n    \"lng\": -98.5238,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Texas\",\n    \"capital\": null,\n    \"population\": 1910785.0,\n    \"id\": 1840022220\n  },\n  {\n    \"city\": \"El Paso\",\n    \"city_ascii\": \"El Paso\",\n    \"lat\": 31.8476,\n    \"lng\": -106.43,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Texas\",\n    \"capital\": null,\n    \"population\": 794344.0,\n    \"id\": 1840023252\n  },\n  {\n    \"city\": \"Boise\",\n    \"city_ascii\": \"Boise\",\n    \"lat\": 43.6005,\n    \"lng\": -116.2308,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Idaho\",\n    \"capital\": \"admin\",\n    \"population\": 422665.0,\n    \"id\": 1840027142\n  },\n  {\n    \"city\": \"Augusta\",\n    \"city_ascii\": \"Augusta\",\n    \"lat\": 33.3645,\n    \"lng\": -82.0708,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Georgia\",\n    \"capital\": null,\n    \"population\": 409668.0,\n    \"id\": 1840029462\n  },\n  {\n    \"city\": \"Indianapolis\",\n    \"city_ascii\": \"Indianapolis\",\n    \"lat\": 39.7771,\n    \"lng\": -86.1458,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Indiana\",\n    \"capital\": \"admin\",\n    \"population\": 1659305.0,\n    \"id\": 1840030084\n  },\n  {\n    \"city\": \"Louisville\",\n    \"city_ascii\": \"Louisville\",\n    \"lat\": 38.1663,\n    \"lng\": -85.6485,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Kentucky\",\n    \"capital\": null,\n    \"population\": 1022630.0,\n    \"id\": 1840030815\n  },\n  {\n    \"city\": \"Bronx\",\n    \"city_ascii\": \"Bronx\",\n    \"lat\": 40.8501,\n    \"lng\": -73.8662,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 1472654.0,\n    \"id\": 1840033999\n  },\n  {\n    \"city\": \"Manhattan\",\n    \"city_ascii\": \"Manhattan\",\n    \"lat\": 40.7834,\n    \"lng\": -73.9662,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 1694263.0,\n    \"id\": 1840034000\n  },\n  {\n    \"city\": \"Queens\",\n    \"city_ascii\": \"Queens\",\n    \"lat\": 40.7498,\n    \"lng\": -73.7976,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 2405464.0,\n    \"id\": 1840034002\n  },\n  {\n    \"city\": \"New York\",\n    \"city_ascii\": \"New York\",\n    \"lat\": 40.6943,\n    \"lng\": -73.9249,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 18972871.0,\n    \"id\": 1840034016\n  },\n  {\n    \"city\": \"Brooklyn\",\n    \"city_ascii\": \"Brooklyn\",\n    \"lat\": 40.6501,\n    \"lng\": -73.9496,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 2736074.0,\n    \"id\": 1840034030\n  },\n  {\n    \"city\": \"Staten Island\",\n    \"city_ascii\": \"Staten Island\",\n    \"lat\": 40.5834,\n    \"lng\": -74.1496,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 495747.0,\n    \"id\": 1840034032\n  },\n  {\n    \"city\": \"Dayton\",\n    \"city_ascii\": \"Dayton\",\n    \"lat\": 39.7805,\n    \"lng\": -84.2003,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Ohio\",\n    \"capital\": null,\n    \"population\": 709300.0,\n    \"id\": 1840034249\n  },\n  {\n    \"city\": \"Nashville\",\n    \"city_ascii\": \"Nashville\",\n    \"lat\": 36.1715,\n    \"lng\": -86.7842,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"Tennessee\",\n    \"capital\": \"admin\",\n    \"population\": 1098486.0,\n    \"id\": 1840036155\n  },\n  {\n    \"city\": \"Brookhaven\",\n    \"city_ascii\": \"Brookhaven\",\n    \"lat\": 40.832,\n    \"lng\": -72.9517,\n    \"country\": \"United States\",\n    \"iso2\": \"US\",\n    \"iso3\": \"USA\",\n    \"admin_name\": \"New York\",\n    \"capital\": null,\n    \"population\": 485984.0,\n    \"id\": 1840057464\n  },\n  {\n    \"city\": \"Ouagadougou\",\n    \"city_ascii\": \"Ouagadougou\",\n    \"lat\": 12.3686,\n    \"lng\": -1.5275,\n    \"country\": \"Burkina Faso\",\n    \"iso2\": \"BF\",\n    \"iso3\": \"BFA\",\n    \"admin_name\": \"Centre\",\n    \"capital\": \"primary\",\n    \"population\": 2453496.0,\n    \"id\": 1854029208\n  },\n  {\n    \"city\": \"Bobo-Dioulasso\",\n    \"city_ascii\": \"Bobo-Dioulasso\",\n    \"lat\": 11.1833,\n    \"lng\": -4.2833,\n    \"country\": \"Burkina Faso\",\n    \"iso2\": \"BF\",\n    \"iso3\": \"BFA\",\n    \"admin_name\": \"Hauts-Bassins\",\n    \"capital\": \"admin\",\n    \"population\": 903887.0,\n    \"id\": 1854348796\n  },\n  {\n    \"city\": \"Montevideo\",\n    \"city_ascii\": \"Montevideo\",\n    \"lat\": -34.8836,\n    \"lng\": -56.1819,\n    \"country\": \"Uruguay\",\n    \"iso2\": \"UY\",\n    \"iso3\": \"URY\",\n    \"admin_name\": \"Montevideo\",\n    \"capital\": \"primary\",\n    \"population\": 1719453.0,\n    \"id\": 1858107000\n  },\n  {\n    \"city\": \"Tashkent\",\n    \"city_ascii\": \"Tashkent\",\n    \"lat\": 41.3111,\n    \"lng\": 69.2797,\n    \"country\": \"Uzbekistan\",\n    \"iso2\": \"UZ\",\n    \"iso3\": \"UZB\",\n    \"admin_name\": \"Toshkent\",\n    \"capital\": \"primary\",\n    \"population\": 2571668.0,\n    \"id\": 1860331871\n  },\n  {\n    \"city\": \"Samarkand\",\n    \"city_ascii\": \"Samarkand\",\n    \"lat\": 39.6547,\n    \"lng\": 66.9758,\n    \"country\": \"Uzbekistan\",\n    \"iso2\": \"UZ\",\n    \"iso3\": \"UZB\",\n    \"admin_name\": \"Samarqand\",\n    \"capital\": \"admin\",\n    \"population\": 546303.0,\n    \"id\": 1860388706\n  },\n  {\n    \"city\": \"Qo‘qon\",\n    \"city_ascii\": \"Qo`qon\",\n    \"lat\": 40.5286,\n    \"lng\": 70.9425,\n    \"country\": \"Uzbekistan\",\n    \"iso2\": \"UZ\",\n    \"iso3\": \"UZB\",\n    \"admin_name\": \"Farg‘ona\",\n    \"capital\": null,\n    \"population\": 350000.0,\n    \"id\": 1860403462\n  },\n  {\n    \"city\": \"Andijon\",\n    \"city_ascii\": \"Andijon\",\n    \"lat\": 40.7833,\n    \"lng\": 72.3333,\n    \"country\": \"Uzbekistan\",\n    \"iso2\": \"UZ\",\n    \"iso3\": \"UZB\",\n    \"admin_name\": \"Andijon\",\n    \"capital\": \"admin\",\n    \"population\": 441700.0,\n    \"id\": 1860445095\n  },\n  {\n    \"city\": \"Namangan\",\n    \"city_ascii\": \"Namangan\",\n    \"lat\": 41.0011,\n    \"lng\": 71.6683,\n    \"country\": \"Uzbekistan\",\n    \"iso2\": \"UZ\",\n    \"iso3\": \"UZB\",\n    \"admin_name\": \"Namangan\",\n    \"capital\": \"admin\",\n    \"population\": 626120.0,\n    \"id\": 1860894033\n  },\n  {\n    \"city\": \"Maracaibo\",\n    \"city_ascii\": \"Maracaibo\",\n    \"lat\": 10.6333,\n    \"lng\": -71.6333,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Zulia\",\n    \"capital\": \"admin\",\n    \"population\": 2658355.0,\n    \"id\": 1862072711\n  },\n  {\n    \"city\": \"Maracay\",\n    \"city_ascii\": \"Maracay\",\n    \"lat\": 10.2469,\n    \"lng\": -67.5958,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Aragua\",\n    \"capital\": \"admin\",\n    \"population\": 407109.0,\n    \"id\": 1862284350\n  },\n  {\n    \"city\": \"Valencia\",\n    \"city_ascii\": \"Valencia\",\n    \"lat\": 10.1667,\n    \"lng\": -68.0,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Carabobo\",\n    \"capital\": \"admin\",\n    \"population\": 1484430.0,\n    \"id\": 1862309871\n  },\n  {\n    \"city\": \"Ciudad Bolívar\",\n    \"city_ascii\": \"Ciudad Bolivar\",\n    \"lat\": 8.1219,\n    \"lng\": -63.55,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Bolívar\",\n    \"capital\": \"admin\",\n    \"population\": 567953.0,\n    \"id\": 1862318264\n  },\n  {\n    \"city\": \"Cabimas\",\n    \"city_ascii\": \"Cabimas\",\n    \"lat\": 10.4,\n    \"lng\": -71.4333,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Zulia\",\n    \"capital\": \"minor\",\n    \"population\": 351735.0,\n    \"id\": 1862398719\n  },\n  {\n    \"city\": \"Barcelona\",\n    \"city_ascii\": \"Barcelona\",\n    \"lat\": 10.1333,\n    \"lng\": -64.6833,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Anzoátegui\",\n    \"capital\": \"admin\",\n    \"population\": 448016.0,\n    \"id\": 1862418619\n  },\n  {\n    \"city\": \"Santa Teresa del Tuy\",\n    \"city_ascii\": \"Santa Teresa del Tuy\",\n    \"lat\": 10.2333,\n    \"lng\": -66.65,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Miranda\",\n    \"capital\": \"minor\",\n    \"population\": 525321.0,\n    \"id\": 1862528581\n  },\n  {\n    \"city\": \"Maturín\",\n    \"city_ascii\": \"Maturin\",\n    \"lat\": 9.7423,\n    \"lng\": -63.1889,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Monagas\",\n    \"capital\": \"admin\",\n    \"population\": 514046.0,\n    \"id\": 1862546949\n  },\n  {\n    \"city\": \"Cumaná\",\n    \"city_ascii\": \"Cumana\",\n    \"lat\": 10.45,\n    \"lng\": -64.1667,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Sucre\",\n    \"capital\": \"admin\",\n    \"population\": 374706.0,\n    \"id\": 1862583279\n  },\n  {\n    \"city\": \"Petare\",\n    \"city_ascii\": \"Petare\",\n    \"lat\": 10.4833,\n    \"lng\": -66.8167,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Miranda\",\n    \"capital\": \"minor\",\n    \"population\": 369000.0,\n    \"id\": 1862595613\n  },\n  {\n    \"city\": \"Barinas\",\n    \"city_ascii\": \"Barinas\",\n    \"lat\": 8.6333,\n    \"lng\": -70.2,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Barinas\",\n    \"capital\": \"admin\",\n    \"population\": 816264.0,\n    \"id\": 1862647790\n  },\n  {\n    \"city\": \"Catia La Mar\",\n    \"city_ascii\": \"Catia La Mar\",\n    \"lat\": 10.6,\n    \"lng\": -67.0333,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"La Guaira\",\n    \"capital\": \"minor\",\n    \"population\": 661897.0,\n    \"id\": 1862657837\n  },\n  {\n    \"city\": \"Caracas\",\n    \"city_ascii\": \"Caracas\",\n    \"lat\": 10.4806,\n    \"lng\": -66.9036,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Distrito Capital\",\n    \"capital\": \"primary\",\n    \"population\": 2245744.0,\n    \"id\": 1862748204\n  },\n  {\n    \"city\": \"Barquisimeto\",\n    \"city_ascii\": \"Barquisimeto\",\n    \"lat\": 10.0678,\n    \"lng\": -69.3467,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Lara\",\n    \"capital\": \"admin\",\n    \"population\": 1059092.0,\n    \"id\": 1862860739\n  },\n  {\n    \"city\": \"Ciudad Guayana\",\n    \"city_ascii\": \"Ciudad Guayana\",\n    \"lat\": 8.3667,\n    \"lng\": -62.65,\n    \"country\": \"Venezuela\",\n    \"iso2\": \"VE\",\n    \"iso3\": \"VEN\",\n    \"admin_name\": \"Bolívar\",\n    \"capital\": \"minor\",\n    \"population\": 751331.0,\n    \"id\": 1862889027\n  },\n  {\n    \"city\": \"Ibb\",\n    \"city_ascii\": \"Ibb\",\n    \"lat\": 13.9667,\n    \"lng\": 44.1667,\n    \"country\": \"Yemen\",\n    \"iso2\": \"YE\",\n    \"iso3\": \"YEM\",\n    \"admin_name\": \"Ibb\",\n    \"capital\": \"admin\",\n    \"population\": 350864.0,\n    \"id\": 1887321491\n  },\n  {\n    \"city\": \"Ta‘izz\",\n    \"city_ascii\": \"Ta`izz\",\n    \"lat\": 13.5789,\n    \"lng\": 44.0219,\n    \"country\": \"Yemen\",\n    \"iso2\": \"YE\",\n    \"iso3\": \"YEM\",\n    \"admin_name\": \"Ta‘izz\",\n    \"capital\": \"admin\",\n    \"population\": 615467.0,\n    \"id\": 1887324526\n  },\n  {\n    \"city\": \"Sanaa\",\n    \"city_ascii\": \"Sanaa\",\n    \"lat\": 15.3483,\n    \"lng\": 44.2064,\n    \"country\": \"Yemen\",\n    \"iso2\": \"YE\",\n    \"iso3\": \"YEM\",\n    \"admin_name\": \"Amānat al ‘Āşimah\",\n    \"capital\": \"primary\",\n    \"population\": 2957000.0,\n    \"id\": 1887750814\n  },\n  {\n    \"city\": \"Aden\",\n    \"city_ascii\": \"Aden\",\n    \"lat\": 12.8,\n    \"lng\": 45.0333,\n    \"country\": \"Yemen\",\n    \"iso2\": \"YE\",\n    \"iso3\": \"YEM\",\n    \"admin_name\": \"‘Adan\",\n    \"capital\": \"admin\",\n    \"population\": 507355.0,\n    \"id\": 1887867886\n  },\n  {\n    \"city\": \"Al Ḩudaydah\",\n    \"city_ascii\": \"Al Hudaydah\",\n    \"lat\": 14.8022,\n    \"lng\": 42.9511,\n    \"country\": \"Yemen\",\n    \"iso2\": \"YE\",\n    \"iso3\": \"YEM\",\n    \"admin_name\": \"Al Ḩudaydah\",\n    \"capital\": \"admin\",\n    \"population\": 548433.0,\n    \"id\": 1887984890\n  },\n  {\n    \"city\": \"Ndola\",\n    \"city_ascii\": \"Ndola\",\n    \"lat\": -12.9667,\n    \"lng\": 28.6333,\n    \"country\": \"Zambia\",\n    \"iso2\": \"ZM\",\n    \"iso3\": \"ZMB\",\n    \"admin_name\": \"Copperbelt\",\n    \"capital\": \"admin\",\n    \"population\": 528330.0,\n    \"id\": 1894032745\n  },\n  {\n    \"city\": \"Lusaka\",\n    \"city_ascii\": \"Lusaka\",\n    \"lat\": -15.4167,\n    \"lng\": 28.2833,\n    \"country\": \"Zambia\",\n    \"iso2\": \"ZM\",\n    \"iso3\": \"ZMB\",\n    \"admin_name\": \"Lusaka\",\n    \"capital\": \"primary\",\n    \"population\": 2467563.0,\n    \"id\": 1894157390\n  },\n  {\n    \"city\": \"Kitwe\",\n    \"city_ascii\": \"Kitwe\",\n    \"lat\": -12.8167,\n    \"lng\": 28.2,\n    \"country\": \"Zambia\",\n    \"iso2\": \"ZM\",\n    \"iso3\": \"ZMB\",\n    \"admin_name\": \"Copperbelt\",\n    \"capital\": null,\n    \"population\": 504194.0,\n    \"id\": 1894321752\n  },\n  {\n    \"city\": \"Gaza\",\n    \"city_ascii\": \"Gaza\",\n    \"lat\": 31.5069,\n    \"lng\": 34.456,\n    \"country\": \"Gaza Strip\",\n    \"iso2\": \"XG\",\n    \"iso3\": \"XGZ\",\n    \"admin_name\": null,\n    \"capital\": \"primary\",\n    \"population\": 590481.0,\n    \"id\": 1916116052\n  }\n]\n"
  },
  {
    "path": "demo/components_list.py",
    "content": "from __future__ import annotations as _annotations\n\nimport asyncio\n\nfrom fastapi import APIRouter\nfrom fastui import AnyComponent, FastUI\nfrom fastui import components as c\nfrom fastui.events import GoToEvent, PageEvent\n\nfrom .shared import demo_page\n\nrouter = APIRouter()\n\n\ndef panel(*components: AnyComponent) -> AnyComponent:\n    return c.Div(class_name='col border rounded m-1 p-2 pb-3', components=list(components))\n\n\n@router.get('', response_model=FastUI, response_model_exclude_none=True)\ndef components_view() -> list[AnyComponent]:\n    return demo_page(\n        c.Div(\n            components=[\n                c.Heading(text='Text', level=2),\n                c.Text(text='This is a text component.'),\n            ]\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Paragraph', level=2),\n                c.Paragraph(text='This is a paragraph component.'),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Heading', level=2),\n                c.Heading(text='This is an H3', level=3),\n                c.Heading(text='This is an H4', level=4),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Code', level=2),\n                c.Code(\n                    language='python',\n                    text=\"\"\"\\\nfrom pydantic import BaseModel\n\nclass Delivery(BaseModel):\n    dimensions: tuple[int, int]\n\nm = Delivery(dimensions=['10', '20'])\nprint(m.dimensions)\n#> (10, 20)\n\"\"\",\n                ),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Link List', level=2),\n                c.Markdown(\n                    text=(\n                        'This is a simple unstyled list of links, '\n                        'LinkList is also used in `Navbar` and `Pagination`.'\n                    )\n                ),\n                c.LinkList(\n                    links=[\n                        c.Link(\n                            components=[c.Text(text='Internal Link - the the home page')],\n                            on_click=GoToEvent(url='/'),\n                        ),\n                        c.Link(\n                            components=[c.Text(text='Pydantic (External link)')],\n                            on_click=GoToEvent(url='https://pydantic.dev'),\n                        ),\n                        c.Link(\n                            components=[c.Text(text='FastUI repo (New tab)')],\n                            on_click=GoToEvent(url='https://github.com/pydantic/FastUI', target='_blank'),\n                        ),\n                    ],\n                ),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Button and Modal', level=2),\n                c.Paragraph(text='The button below will open a modal with static content.'),\n                c.Button(text='Show Static Modal', on_click=PageEvent(name='static-modal')),\n                c.Button(text='Secondary Button', named_style='secondary', class_name='+ ms-2'),\n                c.Button(text='Warning Button', named_style='warning', class_name='+ ms-2'),\n                c.Modal(\n                    title='Static Modal',\n                    body=[c.Paragraph(text='This is some static content that was set when the modal was defined.')],\n                    footer=[\n                        c.Button(text='Close', on_click=PageEvent(name='static-modal', clear=True)),\n                    ],\n                    open_trigger=PageEvent(name='static-modal'),\n                ),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Dynamic Modal', level=2),\n                c.Markdown(\n                    text=(\n                        'The button below will open a modal with content loaded from the server when '\n                        \"it's opened using `ServerLoad`.\"\n                    )\n                ),\n                c.Button(text='Show Dynamic Modal', on_click=PageEvent(name='dynamic-modal')),\n                c.Modal(\n                    title='Dynamic Modal',\n                    body=[c.ServerLoad(path='/components/dynamic-content')],\n                    footer=[\n                        c.Button(text='Close', on_click=PageEvent(name='dynamic-modal', clear=True)),\n                    ],\n                    open_trigger=PageEvent(name='dynamic-modal'),\n                ),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Modal Form / Confirm prompt', level=2),\n                c.Markdown(text='The button below will open a modal with a form.'),\n                c.Button(text='Show Modal Form', on_click=PageEvent(name='modal-form')),\n                c.Modal(\n                    title='Modal Form',\n                    body=[\n                        c.Paragraph(text='Form inside a modal!'),\n                        c.Form(\n                            form_fields=[\n                                c.FormFieldInput(name='foobar', title='Foobar', required=True),\n                            ],\n                            submit_url='/api/components/modal-form',\n                            footer=[],\n                            submit_trigger=PageEvent(name='modal-form-submit'),\n                        ),\n                    ],\n                    footer=[\n                        c.Button(\n                            text='Cancel', named_style='secondary', on_click=PageEvent(name='modal-form', clear=True)\n                        ),\n                        c.Button(text='Submit', on_click=PageEvent(name='modal-form-submit')),\n                    ],\n                    open_trigger=PageEvent(name='modal-form'),\n                ),\n                c.Button(text='Show Modal Prompt', on_click=PageEvent(name='modal-prompt'), class_name='+ ms-2'),\n                c.Modal(\n                    title='Form Prompt',\n                    body=[\n                        c.Paragraph(text='Are you sure you want to do whatever?'),\n                        c.Form(\n                            form_fields=[],\n                            submit_url='/api/components/modal-prompt',\n                            loading=[c.Spinner(text='Okay, good luck...')],\n                            footer=[],\n                            submit_trigger=PageEvent(name='modal-form-submit'),\n                        ),\n                    ],\n                    footer=[\n                        c.Button(\n                            text='Cancel', named_style='secondary', on_click=PageEvent(name='modal-prompt', clear=True)\n                        ),\n                        c.Button(text='Submit', on_click=PageEvent(name='modal-form-submit')),\n                    ],\n                    open_trigger=PageEvent(name='modal-prompt'),\n                ),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Server Load', level=2),\n                c.Paragraph(text='Even simpler example of server load, replacing existing content.'),\n                c.Button(text='Load Content from Server', on_click=PageEvent(name='server-load')),\n                c.Div(\n                    components=[\n                        c.ServerLoad(\n                            path='/components/dynamic-content',\n                            load_trigger=PageEvent(name='server-load'),\n                            components=[c.Text(text='before')],\n                        ),\n                    ],\n                    class_name='py-2',\n                ),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Server Load SSE', level=2),\n                c.Markdown(\n                    text=(\n                        '`ServerLoad` can also be used to load content from an SSE stream.\\n\\n'\n                        \"Here the response is the streamed output from OpenAI's GPT-4 chat model.\"\n                    )\n                ),\n                c.Button(text='Load SSE content', on_click=PageEvent(name='server-load-sse')),\n                c.Div(\n                    components=[\n                        c.ServerLoad(\n                            path='/components/sse',\n                            sse=True,\n                            load_trigger=PageEvent(name='server-load-sse'),\n                            components=[c.Text(text='before')],\n                        ),\n                    ],\n                    class_name='my-2 p-2 border rounded',\n                ),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Iframe', level=2),\n                c.Markdown(text='`Iframe` can be used to embed external content.'),\n                c.Iframe(src='https://pydantic.dev', width='100%', height=400),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Image', level=2),\n                c.Paragraph(text='An image component.'),\n                c.Image(\n                    src='https://avatars.githubusercontent.com/u/110818415',\n                    alt='Pydantic Logo',\n                    width=200,\n                    height=200,\n                    loading='lazy',\n                    referrer_policy='no-referrer',\n                    class_name='border rounded',\n                ),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Spinner', level=2),\n                c.Paragraph(\n                    text=(\n                        'A component displayed while waiting for content to load, '\n                        'this is also used automatically while loading server content.'\n                    )\n                ),\n                c.Spinner(text='Content incoming...'),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Video', level=2),\n                c.Paragraph(text='A video component.'),\n                c.Video(\n                    sources=['https://www.w3schools.com/html/mov_bbb.mp4'],\n                    autoplay=False,\n                    controls=True,\n                    loop=False,\n                ),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Custom', level=2),\n                c.Markdown(\n                    text=\"\"\"\\\nBelow is a custom component, in this case it implements [cowsay](https://en.wikipedia.org/wiki/Cowsay),\nbut you might be able to do something even more useful with it.\n\nThe statement spoken by the famous cow is provided by the backend.\"\"\"\n                ),\n                c.Custom(data='This is a custom component', sub_type='cowsay'),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        c.Div(\n            components=[\n                c.Heading(text='Button and Toast', level=2),\n                c.Paragraph(text='The button below will open a toast.'),\n                c.Button(text='Show Toast', on_click=PageEvent(name='show-toast')),\n                c.Toast(\n                    title='Toast',\n                    body=[c.Paragraph(text='This is a toast.')],\n                    open_trigger=PageEvent(name='show-toast'),\n                    position='bottom-end',\n                ),\n            ],\n            class_name='border-top mt-3 pt-1',\n        ),\n        title='Components',\n    )\n\n\n@router.get('/dynamic-content', response_model=FastUI, response_model_exclude_none=True)\nasync def modal_view() -> list[AnyComponent]:\n    await asyncio.sleep(0.5)\n    return [c.Paragraph(text='This is some dynamic content. Open devtools to see me being fetched from the server.')]\n\n\n@router.post('/modal-form', response_model=FastUI, response_model_exclude_none=True)\nasync def modal_form_submit() -> list[AnyComponent]:\n    await asyncio.sleep(0.5)\n    return [c.FireEvent(event=PageEvent(name='modal-form', clear=True))]\n\n\n@router.post('/modal-prompt', response_model=FastUI, response_model_exclude_none=True)\nasync def modal_prompt_submit() -> list[AnyComponent]:\n    await asyncio.sleep(0.5)\n    return [c.FireEvent(event=PageEvent(name='modal-prompt', clear=True))]\n"
  },
  {
    "path": "demo/forms.py",
    "content": "from __future__ import annotations as _annotations\n\nimport enum\nfrom collections import defaultdict\nfrom datetime import date\nfrom typing import Annotated, Literal, TypeAlias\n\nfrom fastapi import APIRouter, Request, UploadFile\nfrom fastui import AnyComponent, FastUI\nfrom fastui import components as c\nfrom fastui.events import GoToEvent, PageEvent\nfrom fastui.forms import FormFile, SelectSearchResponse, Textarea, fastui_form\nfrom httpx import AsyncClient\nfrom pydantic import BaseModel, EmailStr, Field, SecretStr, field_validator\nfrom pydantic_core import PydanticCustomError\n\nfrom .shared import demo_page\n\nrouter = APIRouter()\n\n\n@router.get('/search', response_model=SelectSearchResponse)\nasync def search_view(request: Request, q: str) -> SelectSearchResponse:\n    path_ends = f'name/{q}' if q else 'all'\n    client: AsyncClient = request.app.state.httpx_client\n    r = await client.get(f'https://restcountries.com/v3.1/{path_ends}')\n    if r.status_code == 404:\n        options = []\n    else:\n        r.raise_for_status()\n        data = r.json()\n        if path_ends == 'all':\n            # if we got all, filter to the 20 most populous countries\n            data.sort(key=lambda x: x['population'], reverse=True)\n            data = data[0:20]\n            data.sort(key=lambda x: x['name']['common'])\n\n        regions = defaultdict(list)\n        for co in data:\n            regions[co['region']].append({'value': co['cca3'], 'label': co['name']['common']})\n        options = [{'label': k, 'options': v} for k, v in regions.items()]\n    return SelectSearchResponse(options=options)\n\n\nFormKind: TypeAlias = Literal['login', 'select', 'big']\n\n\n@router.get('/{kind}', response_model=FastUI, response_model_exclude_none=True)\ndef forms_view(kind: FormKind) -> list[AnyComponent]:\n    return demo_page(\n        c.LinkList(\n            links=[\n                c.Link(\n                    components=[c.Text(text='Login Form')],\n                    on_click=PageEvent(name='change-form', push_path='/forms/login', context={'kind': 'login'}),\n                    active='/forms/login',\n                ),\n                c.Link(\n                    components=[c.Text(text='Select Form')],\n                    on_click=PageEvent(name='change-form', push_path='/forms/select', context={'kind': 'select'}),\n                    active='/forms/select',\n                ),\n                c.Link(\n                    components=[c.Text(text='Big Form')],\n                    on_click=PageEvent(name='change-form', push_path='/forms/big', context={'kind': 'big'}),\n                    active='/forms/big',\n                ),\n            ],\n            mode='tabs',\n            class_name='+ mb-4',\n        ),\n        c.ServerLoad(\n            path='/forms/content/{kind}',\n            load_trigger=PageEvent(name='change-form'),\n            components=form_content(kind),\n        ),\n        title='Forms',\n    )\n\n\n@router.get('/content/{kind}', response_model=FastUI, response_model_exclude_none=True)\ndef form_content(kind: FormKind):\n    match kind:\n        case 'login':\n            return [\n                c.Heading(text='Login Form', level=2),\n                c.Paragraph(text='Simple login form with email and password.'),\n                c.ModelForm(model=LoginForm, display_mode='page', submit_url='/api/forms/login'),\n            ]\n        case 'select':\n            return [\n                c.Heading(text='Select Form', level=2),\n                c.Paragraph(text='Form showing different ways of doing select.'),\n                c.ModelForm(model=SelectForm, display_mode='page', submit_url='/api/forms/select'),\n            ]\n        case 'big':\n            return [\n                c.Heading(text='Large Form', level=2),\n                c.Paragraph(text='Form with a lot of fields.'),\n                c.ModelForm(model=BigModel, display_mode='page', submit_url='/api/forms/big'),\n            ]\n        case _:\n            raise ValueError(f'Invalid kind {kind!r}')\n\n\nclass LoginForm(BaseModel):\n    email: EmailStr = Field(title='Email Address', description=\"Try 'x@y' to trigger server side validation\")\n    password: SecretStr\n\n\n@router.post('/login', response_model=FastUI, response_model_exclude_none=True)\nasync def login_form_post(form: Annotated[LoginForm, fastui_form(LoginForm)]):\n    print(form)\n    return [c.FireEvent(event=GoToEvent(url='/'))]\n\n\nclass ToolEnum(str, enum.Enum):\n    hammer = 'hammer'\n    screwdriver = 'screwdriver'\n    saw = 'saw'\n    claw_hammer = 'claw_hammer'\n\n\nclass SelectForm(BaseModel):\n    select_single: ToolEnum = Field(title='Select Single')\n    select_multiple: list[ToolEnum] = Field(title='Select Multiple')\n    search_select_single: str = Field(json_schema_extra={'search_url': '/api/forms/search'})\n    search_select_multiple: list[str] = Field(json_schema_extra={'search_url': '/api/forms/search'})\n\n    @field_validator('select_multiple', 'search_select_multiple', mode='before')\n    @classmethod\n    def correct_select_multiple(cls, v: list[str]) -> list[str]:\n        if isinstance(v, list):\n            return v\n        else:\n            return [v]\n\n\n@router.post('/select', response_model=FastUI, response_model_exclude_none=True)\nasync def select_form_post(form: Annotated[SelectForm, fastui_form(SelectForm)]):\n    # print(form)\n    return [c.FireEvent(event=GoToEvent(url='/'))]\n\n\nclass SizeModel(BaseModel):\n    width: int = Field(description='This is a field of a nested model')\n    height: int = Field(description='This is a field of a nested model')\n\n\nclass BigModel(BaseModel):\n    name: str | None = Field(\n        None, description='This field is not required, it must start with a capital letter if provided'\n    )\n    info: Annotated[str | None, Textarea(rows=5)] = Field(None, description='Optional free text information about you.')\n    repo: str = Field(json_schema_extra={'placeholder': '{org}/{repo}'}, title='GitHub repository')\n    profile_pic: Annotated[UploadFile, FormFile(accept='image/*', max_size=16_000)] = Field(\n        description='Upload a profile picture, must not be more than 16kb'\n    )\n    profile_pics: Annotated[list[UploadFile], FormFile(accept='image/*')] | None = Field(\n        None, description='Upload multiple images'\n    )\n    dob: date = Field(title='Date of Birth', description='Your date of birth, this is required hence bold')\n    human: bool | None = Field(\n        None, title='Is human', description='Are you human?', json_schema_extra={'mode': 'switch'}\n    )\n    size: SizeModel\n\n    position: tuple[\n        Annotated[int, Field(description='X Coordinate')],\n        Annotated[int, Field(description='Y Coordinate')],\n    ]\n\n    @field_validator('name')\n    def name_validator(cls, v: str | None) -> str:\n        if v and v[0].islower():\n            raise PydanticCustomError('lower', 'Name must start with a capital letter')\n        return v\n\n\n@router.post('/big', response_model=FastUI, response_model_exclude_none=True)\nasync def big_form_post(form: Annotated[BigModel, fastui_form(BigModel)]):\n    print(form)\n    return [c.FireEvent(event=GoToEvent(url='/'))]\n"
  },
  {
    "path": "demo/main.py",
    "content": "from __future__ import annotations as _annotations\n\nfrom fastapi import APIRouter\nfrom fastui import AnyComponent, FastUI\nfrom fastui import components as c\n\nfrom .shared import demo_page\n\nrouter = APIRouter()\n\n\n@router.get('/', response_model=FastUI, response_model_exclude_none=True)\ndef api_index() -> list[AnyComponent]:\n    # language=markdown\n    markdown = \"\"\"\\\nThis site provides a demo of [FastUI](https://github.com/pydantic/FastUI), the code for the demo\nis [here](https://github.com/pydantic/FastUI/tree/main/demo).\n\nYou can find the documentation for FastUI [here](https://docs.pydantic.dev/fastui/).\n\nThe following components are demonstrated:\n\n* `Markdown` — that's me :-)\n* `Text`— example [here](/components#text)\n* `Paragraph` — example [here](/components#paragraph)\n* `PageTitle` — you'll see the title in the browser tab change when you navigate through the site\n* `Heading` — example [here](/components#heading)\n* `Code` — example [here](/components#code)\n* `Button` — example [here](/components#button-and-modal)\n* `Link` — example [here](/components#link-list)\n* `LinkList` — example [here](/components#link-list)\n* `Navbar` — see the top of this page\n* `Footer` — see the bottom of this page\n* `Modal` — static example [here](/components#button-and-modal), dynamic content example [here](/components#dynamic-modal)\n* `ServerLoad` — see [dynamic modal example](/components#dynamic-modal) and [SSE example](/components#server-load-sse)\n* `Image` - example [here](/components#image)\n* `Iframe` - example [here](/components#iframe)\n* `Video` - example [here](/components#video)\n* `Toast` - example [here](/components#toast)\n* `Table` — See [cities table](/table/cities) and [users table](/table/users)\n* `Pagination` — See the bottom of the [cities table](/table/cities)\n* `ModelForm` — See [forms](/forms/login)\n\nAuthentication is supported via:\n* token based authentication — see [here](/auth/login/password) for an example of password authentication\n* GitHub OAuth — see [here](/auth/login/github) for an example of GitHub OAuth login\n\"\"\"\n    return demo_page(c.Markdown(text=markdown))\n\n\n@router.get('/{path:path}', status_code=404)\nasync def api_404():\n    # so we don't fall through to the index page\n    return {'message': 'Not Found'}\n"
  },
  {
    "path": "demo/shared.py",
    "content": "from __future__ import annotations as _annotations\n\nfrom fastui import AnyComponent\nfrom fastui import components as c\nfrom fastui.events import GoToEvent\n\n\ndef demo_page(*components: AnyComponent, title: str | None = None) -> list[AnyComponent]:\n    return [\n        c.PageTitle(text=f'FastUI Demo — {title}' if title else 'FastUI Demo'),\n        c.Navbar(\n            title='FastUI Demo',\n            title_event=GoToEvent(url='/'),\n            start_links=[\n                c.Link(\n                    components=[c.Text(text='Components')],\n                    on_click=GoToEvent(url='/components'),\n                    active='startswith:/components',\n                ),\n                c.Link(\n                    components=[c.Text(text='Tables')],\n                    on_click=GoToEvent(url='/table/cities'),\n                    active='startswith:/table',\n                ),\n                c.Link(\n                    components=[c.Text(text='Auth')],\n                    on_click=GoToEvent(url='/auth/login/password'),\n                    active='startswith:/auth',\n                ),\n                c.Link(\n                    components=[c.Text(text='Forms')],\n                    on_click=GoToEvent(url='/forms/login'),\n                    active='startswith:/forms',\n                ),\n            ],\n        ),\n        c.Page(\n            components=[\n                *((c.Heading(text=title),) if title else ()),\n                *components,\n            ],\n        ),\n        c.Footer(\n            extra_text='FastUI Demo',\n            links=[\n                c.Link(\n                    components=[c.Text(text='Github')], on_click=GoToEvent(url='https://github.com/pydantic/FastUI')\n                ),\n                c.Link(components=[c.Text(text='PyPI')], on_click=GoToEvent(url='https://pypi.org/project/fastui/')),\n                c.Link(components=[c.Text(text='NPM')], on_click=GoToEvent(url='https://www.npmjs.com/org/pydantic/')),\n            ],\n        ),\n    ]\n"
  },
  {
    "path": "demo/sse.py",
    "content": "import asyncio\nfrom collections.abc import AsyncIterable\nfrom itertools import chain\n\nfrom fastapi import APIRouter\nfrom fastui import FastUI\nfrom fastui import components as c\nfrom starlette.responses import StreamingResponse\n\nrouter = APIRouter()\n\n\nasync def canned_ai_response_generator() -> AsyncIterable[str]:\n    prompt = '**User:** What is SSE? Please include a javascript code example.\\n\\n**AI:** '\n    output = ''\n    for time, text in chain([(0.5, prompt)], CANNED_RESPONSE):\n        await asyncio.sleep(time)\n        output += text\n        m = FastUI(root=[c.Markdown(text=output)])\n        yield f'data: {m.model_dump_json(by_alias=True, exclude_none=True)}\\n\\n'\n\n\n@router.get('/sse')\nasync def sse_ai_response() -> StreamingResponse:\n    return StreamingResponse(canned_ai_response_generator(), media_type='text/event-stream')\n\n\nasync def run_openai():\n    from time import perf_counter\n\n    from openai import AsyncOpenAI\n\n    messages = [\n        {'role': 'system', 'content': 'please response in markdown only.'},\n        {'role': 'user', 'content': 'What is SSE? Please include a javascript code example.'},\n    ]\n    chunks = await AsyncOpenAI().chat.completions.create(\n        model='gpt-4',\n        messages=messages,\n        stream=True,\n    )\n\n    last = None\n    result_chunks = []\n    async for chunk in chunks:\n        now = perf_counter()\n        if last is not None:\n            t = now - last\n        else:\n            t = 0\n        text = chunk.choices[0].delta.content\n        print(repr(text), t)\n        if text is not None:\n            result_chunks.append((t, text))\n        last = now\n\n    print(result_chunks)\n    text = ''.join(text for _, text in result_chunks)\n    print(text)\n\n\nif __name__ == '__main__':\n    asyncio.run(run_openai())\n\n\nCANNED_RESPONSE: list[tuple[float, str]] = [\n    (0.00000, ''),\n    (0.07685, 'Server'),\n    (0.00111, '-S'),\n    (0.00081, 'ent'),\n    (0.10528, ' Events'),\n    (0.00109, ' ('),\n    (0.00062, 'S'),\n    (0.10290, 'SE'),\n    (0.00075, ')'),\n    (0.00091, ' is'),\n    (0.10360, ' a'),\n    (0.00089, ' standard'),\n    (0.00054, ' that'),\n    (0.19121, ' allows'),\n    (0.00088, ' web'),\n    (0.00067, ' servers'),\n    (0.22486, ' to'),\n    (0.00101, ' push'),\n    (0.00057, ' updates'),\n    (0.10352, ' to'),\n    (0.00148, ' the'),\n    (0.00084, ' client'),\n    (0.10238, '-side'),\n    (0.00090, '.'),\n    (0.00104, ' Unlike'),\n    (0.10156, ' WebSocket'),\n    (0.00109, ' communication'),\n    (0.00063, ','),\n    (0.10474, ' SSE'),\n    (0.00080, ' is'),\n    (0.00085, ' un'),\n    (0.10158, 'id'),\n    (0.00080, 'irectional'),\n    (0.00097, ','),\n    (0.10401, ' meaning'),\n    (0.00099, ' the'),\n    (0.00104, ' updates'),\n    (0.11338, ' flow'),\n    (0.00078, ' from'),\n    (0.00080, ' server'),\n    (0.09008, ' to'),\n    (0.00072, ' client'),\n    (0.00105, ' and'),\n    (0.10391, ' not'),\n    (0.00084, ' the'),\n    (0.00080, ' other'),\n    (0.10613, ' way'),\n    (0.00110, ' around'),\n    (0.00080, '.\\n\\n'),\n    (0.10567, 'S'),\n    (0.00076, 'SE'),\n    (0.00085, ' is'),\n    (0.09538, ' generally'),\n    (0.00134, ' used'),\n    (0.00052, ' for'),\n    (0.10731, ' real'),\n    (0.00108, '-time'),\n    (0.00079, ' applications'),\n    (0.09934, ' where'),\n    (0.00065, ' updates'),\n    (0.00061, ' from'),\n    (0.10913, ' the'),\n    (0.00111, ' server'),\n    (0.00071, ' are'),\n    (0.09556, ' needed'),\n    (0.00065, ' periodically'),\n    (0.00103, ','),\n    (0.10564, ' for'),\n    (0.00184, ' example'),\n    (0.00077, ','),\n    (0.17375, ' live'),\n    (0.00067, ' news'),\n    (0.00073, ' updates'),\n    (0.02926, ','),\n    (0.00084, ' real'),\n    (0.00052, '-time'),\n    (0.10552, ' monitoring'),\n    (0.00080, ','),\n    (0.00063, ' etc'),\n    (0.10336, '.'),\n    (0.00087, ' It'),\n    (0.00095, ' is'),\n    (0.10473, ' based'),\n    (0.00100, ' on'),\n    (0.00058, ' HTTP'),\n    (0.10139, ' protocol'),\n    (0.00096, ' and'),\n    (0.00049, ' provides'),\n    (0.14795, ' a'),\n    (0.00073, ' simpler'),\n    (0.00088, ' alternative'),\n    (0.10304, ' to'),\n    (0.00092, ' Web'),\n    (0.00055, 'S'),\n    (0.10849, 'ockets'),\n    (0.00076, ' for'),\n    (0.00096, ' use'),\n    (0.09727, ' cases'),\n    (0.00087, ' where'),\n    (0.00080, ' you'),\n    (0.11029, ' do'),\n    (0.00060, ' not'),\n    (0.00046, ' require'),\n    (0.12591, ' bid'),\n    (0.00084, 'irectional'),\n    (0.00064, ' communication'),\n    (0.07139, '.\\n\\n'),\n    (0.00082, '**'),\n    (0.00064, 'JavaScript'),\n    (0.10693, ' Example'),\n    (0.00078, '**\\n\\n'),\n    (0.00064, '```'),\n    (0.14820, 'javascript'),\n    (0.00102, '\\n'),\n    (0.00066, 'let'),\n    (0.10841, ' event'),\n    (0.00073, 'Source'),\n    (0.00112, ' ='),\n    (0.09982, ' new'),\n    (0.00171, ' Event'),\n    (0.00087, 'Source'),\n    (0.10119, '(\"'),\n    (0.00129, 'https'),\n    (0.00078, '://'),\n    (0.10253, 'api'),\n    (0.00080, '.example'),\n    (0.00086, '.com'),\n    (0.10223, '/stream'),\n    (0.00069, '\");\\n\\n'),\n    (0.00051, 'event'),\n    (0.10391, 'Source'),\n    (0.00082, '.on'),\n    (0.00090, 'message'),\n    (0.10570, ' ='),\n    (0.00286, ' function'),\n    (0.00061, '(event'),\n    (0.08790, ')'),\n    (0.00098, ' {\\n'),\n    (0.00058, '   '),\n    (0.09117, ' console'),\n    (0.00061, '.log'),\n    (0.00118, '(\"'),\n    (0.14843, 'New'),\n    (0.00085, ' event'),\n    (0.00054, ' received'),\n    (0.09681, ':'),\n    (0.00078, ' \",'),\n    (0.00092, ' event'),\n    (0.09540, '.data'),\n    (0.00075, ');\\n'),\n    (0.00077, '};\\n\\n'),\n    (0.10102, 'event'),\n    (0.00096, 'Source'),\n    (0.00058, '.onerror'),\n    (0.09409, ' ='),\n    (0.00088, ' function'),\n    (0.00063, '(err'),\n    (0.10187, ')'),\n    (0.00080, ' {\\n'),\n    (0.00062, '   '),\n    (0.10227, ' console'),\n    (0.00098, '.error'),\n    (0.00062, '(\"'),\n    (0.09445, 'Event'),\n    (0.00103, 'Source'),\n    (0.00080, ' failed'),\n    (0.10366, ':\",'),\n    (0.00073, ' err'),\n    (0.00101, ');\\n'),\n    (0.09442, '};\\n'),\n    (0.00088, '``'),\n    (0.00051, '`\\n\\n'),\n    (0.10121, 'Here'),\n    (0.00156, ','),\n    (0.00077, ' `'),\n    (0.09582, 'https'),\n    (0.00072, '://'),\n    (0.00083, 'api'),\n    (0.09987, '.example'),\n    (0.00082, '.com'),\n    (0.00088, '/stream'),\n    (0.10323, '`'),\n    (0.00070, ' is'),\n    (0.00075, ' the'),\n    (0.09308, ' endpoint'),\n    (0.00118, ' which'),\n    (0.00080, ' sends'),\n    (0.10005, ' the'),\n    (0.00091, ' updates'),\n    (0.00091, '.\\n\\n'),\n    (0.09656, '**'),\n    (0.00272, 'Fast'),\n    (0.00068, 'API'),\n    (0.10638, ' Example'),\n    (0.00069, '**\\n\\n'),\n    (0.00068, '```'),\n    (0.09220, 'python'),\n    (0.00068, '\\n'),\n    (0.00102, 'from'),\n    (0.16155, ' fast'),\n    (0.00082, 'api'),\n    (0.00054, ' import'),\n    (0.09223, ' Fast'),\n    (0.00075, 'API'),\n    (0.00064, '\\n'),\n    (0.09892, 'from'),\n    (0.00071, ' fast'),\n    (0.00051, 'api'),\n    (0.00075, '.responses'),\n    (0.00071, ' import'),\n    (0.00058, ' Streaming'),\n    (0.00081, 'Response'),\n    (0.00052, '\\n\\n'),\n    (0.10306, 'app'),\n    (0.00075, ' ='),\n    (0.00088, ' Fast'),\n    (0.09503, 'API'),\n    (0.00260, '()\\n\\n'),\n    (0.00054, 'def'),\n    (0.09160, ' event'),\n    (0.00075, '_generator'),\n    (0.00067, '():\\n'),\n    (0.09801, '   '),\n    (0.00080, ' yield'),\n    (0.00086, \" {'\"),\n    (0.07686, 'data'),\n    (0.00125, \"':\"),\n    (0.00087, \" '\"),\n    (0.08182, 'Initial'),\n    (0.00086, ' message'),\n    (0.00052, \"'}\\n\"),\n    (0.16532, '   '),\n    (0.00114, ' for'),\n    (0.00058, ' i'),\n    (0.10338, ' in'),\n    (0.00080, ' range'),\n    (0.00082, '('),\n    (0.10311, '5'),\n    (0.00075, '):\\n'),\n    (0.00066, '       '),\n    (0.09347, ' yield'),\n    (0.00080, \" {'\"),\n    (0.00060, 'data'),\n    (0.10470, \"':\"),\n    (0.00077, ' f'),\n    (0.00052, \"'M\"),\n    (0.10310, 'essage'),\n    (0.00070, ' {'),\n    (0.00103, 'i'),\n    (0.09362, \"}'\"),\n    (0.00091, '}\\n\\n'),\n    (0.00068, '@app'),\n    (0.09475, '.get'),\n    (0.00078, '(\"/'),\n    (0.00078, 'stream'),\n    (0.08145, '\")\\n'),\n    (0.00064, 'async'),\n    (0.00067, ' def'),\n    (0.08127, ' get'),\n    (0.00141, '_event'),\n    (0.00049, '_stream'),\n    (0.08973, '():\\n'),\n    (0.00095, '   '),\n    (0.00089, ' return'),\n    (0.07297, ' Streaming'),\n    (0.00092, 'Response'),\n    (0.19895, '(event'),\n    (0.00075, '_generator'),\n    (0.00049, '(),'),\n    (0.00092, ' media_type'),\n    (0.00066, '='),\n    (0.00052, \"'text/\"),\n    (0.00073, \"event-stream'\"),\n    (0.00050, ')\\n'),\n    (0.07387, '``'),\n    (0.00066, '`\\n\\n'),\n    (0.00054, 'In'),\n    (0.08289, ' the'),\n    (0.00088, ' Fast'),\n    (0.00093, 'API'),\n    (0.14361, ' example'),\n    (0.00087, ','),\n    (0.00060, ' the'),\n    (0.01910, ' client'),\n    (0.00074, ' would'),\n    (0.00059, ' receive'),\n    (0.08010, ' an'),\n    (0.00232, ' event'),\n    (0.00059, ' with'),\n    (0.07788, \" '\"),\n    (0.00101, 'Initial'),\n    (0.00061, ' message'),\n    (0.50112, \"',\"),\n    (0.00061, ' followed'),\n    (0.00049, ' by'),\n    (0.05819, \" '\"),\n    (0.00072, 'Message'),\n    (0.00060, ' '),\n    (0.11164, '0'),\n    (0.00075, \"',\"),\n    (0.00096, \" '\"),\n    (0.10626, 'Message'),\n    (0.00081, ' '),\n    (0.00051, '1'),\n    (0.11977, \"',\"),\n    (0.00071, ' ...,'),\n    (0.00051, \" '\"),\n    (0.11939, 'Message'),\n    (0.00081, ' '),\n    (0.00059, '4'),\n    (0.11833, \"'.\"),\n    (0.00059, ' Each'),\n    (0.00025, ' message'),\n    (0.11457, ' is'),\n    (0.00063, ' an'),\n    (0.00058, ' individual'),\n    (0.11788, ' Server'),\n    (0.00084, '-S'),\n    (0.00037, 'ent'),\n    (0.00046, ' Event'),\n    (0.00026, '.'),\n]\n"
  },
  {
    "path": "demo/tables.py",
    "content": "from datetime import date\nfrom functools import cache\nfrom pathlib import Path\n\nimport pydantic\nfrom fastapi import APIRouter\nfrom fastui import AnyComponent, FastUI\nfrom fastui import components as c\nfrom fastui.components.display import DisplayLookup, DisplayMode\nfrom fastui.events import BackEvent, GoToEvent\nfrom pydantic import BaseModel, Field, TypeAdapter\n\nfrom .shared import demo_page\n\nrouter = APIRouter()\n\n\nclass City(BaseModel):\n    id: int = Field(title='ID')\n    city: str = Field(title='Name')\n    city_ascii: str = Field(title='City Ascii')\n    lat: float = Field(title='Latitude')\n    lng: float = Field(title='Longitude')\n    country: str = Field(title='Country')\n    iso2: str = Field(title='ISO2')\n    iso3: str = Field(title='ISO3')\n    admin_name: str | None = Field(title='Admin Name')\n    capital: str | None = Field(title='Capital')\n    population: float = Field(title='Population')\n\n\n@cache\ndef cities_list() -> list[City]:\n    cities_adapter = TypeAdapter(list[City])\n    cities_file = Path(__file__).parent / 'cities.json'\n    cities = cities_adapter.validate_json(cities_file.read_bytes())\n    cities.sort(key=lambda city: city.population, reverse=True)\n    return cities\n\n\n@cache\ndef cities_lookup() -> dict[id, City]:\n    return {city.id: city for city in cities_list()}\n\n\nclass FilterForm(pydantic.BaseModel):\n    country: str = Field(json_schema_extra={'search_url': '/api/forms/search', 'placeholder': 'Filter by Country...'})\n\n\n@router.get('/cities', response_model=FastUI, response_model_exclude_none=True)\ndef cities_view(page: int = 1, country: str | None = None) -> list[AnyComponent]:\n    cities = cities_list()\n    page_size = 50\n    filter_form_initial = {}\n    if country:\n        cities = [city for city in cities if city.iso3 == country]\n        country_name = cities[0].country if cities else country\n        filter_form_initial['country'] = {'value': country, 'label': country_name}\n    return demo_page(\n        *tabs(),\n        c.ModelForm(\n            model=FilterForm,\n            submit_url='.',\n            initial=filter_form_initial,\n            method='GOTO',\n            submit_on_change=True,\n            display_mode='inline',\n        ),\n        c.Table(\n            data=cities[(page - 1) * page_size : page * page_size],\n            data_model=City,\n            columns=[\n                DisplayLookup(field='city', on_click=GoToEvent(url='./{id}'), table_width_percent=33),\n                DisplayLookup(field='country', table_width_percent=33),\n                DisplayLookup(field='population', table_width_percent=33),\n            ],\n        ),\n        c.Pagination(page=page, page_size=page_size, total=len(cities)),\n        title='Cities',\n    )\n\n\n@router.get('/cities/{city_id}', response_model=FastUI, response_model_exclude_none=True)\ndef city_view(city_id: int) -> list[AnyComponent]:\n    city = cities_lookup()[city_id]\n    return demo_page(\n        *tabs(),\n        c.Link(components=[c.Text(text='Back')], on_click=BackEvent()),\n        c.Details(data=city),\n        title=city.city,\n    )\n\n\nclass User(BaseModel):\n    id: int = Field(title='ID')\n    name: str = Field(title='Name')\n    dob: date = Field(title='Date of Birth')\n    enabled: bool | None = None\n    status_markdown: str | None = Field(default=None, title='Status')\n\n\nusers: list[User] = [\n    User(id=1, name='John', dob=date(1990, 1, 1), enabled=True, status_markdown='**Active**'),\n    User(id=2, name='Jane', dob=date(1991, 1, 1), enabled=False, status_markdown='*Inactive*'),\n    User(id=3, name='Jack', dob=date(1992, 1, 1)),\n]\n\n\n@router.get('/users', response_model=FastUI, response_model_exclude_none=True)\ndef users_view() -> list[AnyComponent]:\n    return demo_page(\n        *tabs(),\n        c.Table(\n            data=users,\n            columns=[\n                DisplayLookup(field='name', on_click=GoToEvent(url='/table/users/{id}/')),\n                DisplayLookup(field='dob', mode=DisplayMode.date),\n                DisplayLookup(field='enabled'),\n                DisplayLookup(field='status_markdown', mode=DisplayMode.markdown),\n            ],\n        ),\n        title='Users',\n    )\n\n\ndef tabs() -> list[AnyComponent]:\n    return [\n        c.LinkList(\n            links=[\n                c.Link(\n                    components=[c.Text(text='Cities')],\n                    on_click=GoToEvent(url='/table/cities'),\n                    active='startswith:/table/cities',\n                ),\n                c.Link(\n                    components=[c.Text(text='Users')],\n                    on_click=GoToEvent(url='/table/users'),\n                    active='startswith:/table/users',\n                ),\n            ],\n            mode='tabs',\n            class_name='+ mb-4',\n        ),\n    ]\n\n\n@router.get('/users/{id}/', response_model=FastUI, response_model_exclude_none=True)\ndef user_profile(id: int) -> list[AnyComponent]:\n    user: User | None = users[id - 1] if id <= len(users) else None\n    return demo_page(\n        *tabs(),\n        c.Link(components=[c.Text(text='Back')], on_click=BackEvent()),\n        c.Details(\n            data=user,\n            fields=[\n                DisplayLookup(field='name'),\n                DisplayLookup(field='dob', mode=DisplayMode.date),\n                DisplayLookup(field='enabled'),\n            ],\n        ),\n        title=user.name,\n    )\n"
  },
  {
    "path": "demo/tests.py",
    "content": "import re\n\nimport pytest\nfrom dirty_equals import IsList, IsStr\nfrom fastapi.testclient import TestClient\n\nfrom . import app\n\n\n@pytest.fixture\ndef client():\n    with TestClient(app) as test_client:\n        yield test_client\n\n\ndef test_index(client: TestClient):\n    r = client.get('/')\n    assert r.status_code == 200, r.text\n    assert r.text.startswith('<!doctype html>\\n')\n    assert r.headers.get('content-type') == 'text/html; charset=utf-8'\n\n\ndef test_api_root(client: TestClient):\n    r = client.get('/api/')\n    assert r.status_code == 200\n    data = r.json()\n    assert data == [\n        {\n            'text': 'FastUI Demo',\n            'type': 'PageTitle',\n        },\n        {\n            'title': 'FastUI Demo',\n            'titleEvent': {'url': '/', 'type': 'go-to'},\n            'startLinks': IsList(length=4),\n            'endLinks': [],\n            'type': 'Navbar',\n        },\n        {\n            'components': [\n                {\n                    'text': IsStr(regex='This site provides a demo of.*', regex_flags=re.DOTALL),\n                    'type': 'Markdown',\n                },\n            ],\n            'type': 'Page',\n        },\n        {\n            'extraText': 'FastUI Demo',\n            'links': IsList(length=3),\n            'type': 'Footer',\n        },\n    ]\n\n\ndef get_menu_links():\n    \"\"\"\n    This is pretty cursory, we just go through the menu and load each page.\n    \"\"\"\n    with TestClient(app) as client:\n        r = client.get('/api/')\n        assert r.status_code == 200\n        data = r.json()\n        for link in data[1]['startLinks']:\n            url = link['onClick']['url']\n            yield pytest.param(f'/api{url}', id=url)\n\n\n@pytest.mark.parametrize('url', get_menu_links())\ndef test_menu_links(client: TestClient, url: str):\n    r = client.get(url)\n    assert r.status_code == 200\n    data = r.json()\n    assert isinstance(data, list)\n\n\n# def test_forms_validate_correct_select_multiple(client: TestClient):\n#     countries = client.get('api/forms/search', params={'q': None})\n#     countries_options = countries.json()['options']\n#     r = client.post(\n#         'api/forms/select',\n#         data={\n#             'select_single': ToolEnum._member_names_[0],\n#             'select_multiple': ToolEnum._member_names_[0],\n#             'search_select_single': countries_options[0]['options'][0]['value'],\n#             'search_select_multiple': countries_options[0]['options'][0]['value'],\n#         },\n#     )\n#     assert r.status_code == 200\n\n\n# TODO tests for forms, including submission\n"
  },
  {
    "path": "docs/api/python_components.md",
    "content": "# Python Components\n\n::: fastui.components\n    handler: python\n    options:\n        inherited_members: true\n        docstring_options:\n            ignore_init_summary: false\n    members:\n        - Text\n        - Paragraph\n        - PageTitle\n        - Div\n        - Page\n        - Heading\n        - Markdown\n        - Code\n        - Json\n        - Button\n        - Link\n        - LinkList\n        - Navbar\n        - Modal\n        - ServerLoad\n        - Image\n        - Iframe\n        - FireEvent\n        - Error\n        - Spinner\n        - Toast\n        - Custom\n        - Table\n        - Pagination\n        - Display\n        - Details\n        - Form\n        - FormField\n        - ModelForm\n        - Footer\n        - AnyComponent\n        - FormFieldBoolean\n        - FormFieldFile\n        - FormFieldInput\n        - FormFieldSelect\n        - FormFieldSelectSearch\n\n<!-- TODO: don't render attributes in TOC -->\n"
  },
  {
    "path": "docs/api/typescript_components.md",
    "content": "# TypeScript Components\n\n!!! warning \"🚧 Work in Progress\"\n    This page is a work in progress.\n\n<!-- Note -- we will enable this in the future when mkdocstrings-typescript and griffe-typedoc\nHave publicly available options -->\n<!-- ::: @pydantic/fastui\n    handler: typescript -->\n"
  },
  {
    "path": "docs/extra/tweaks.css",
    "content": "/* Revert hue value to that of pre mkdocs-material v9.4.0 */\n[data-md-color-scheme='slate'] {\n  --md-hue: 230;\n  --md-default-bg-color: hsla(230, 15%, 21%, 1);\n}\n"
  },
  {
    "path": "docs/guide.md",
    "content": "!!! warning \"🚧 Work in Progress\"\n    This page is a work in progress.\n"
  },
  {
    "path": "docs/index.md",
    "content": "# FastUI\n\n## The Principle\n\nFastUI is a new way to build web application user interfaces defined by declarative Python code.\n\nThis means:\n\n- **If you're a Python developer** — you can build responsive web applications using React without writing a single line of JavaScript, or touching `npm`.\n- **If you're a frontend developer** — you can concentrate on building magical components that are truly reusable, no copy-pasting components for each view.\n- **For everyone** — a true separation of concerns, the backend defines the entire application; while the frontend is free to implement just the user interface\n\nAt its heart, FastUI is a set of matching [Pydantic](https://docs.pydantic.dev) models and TypeScript interfaces that allow you to define a user interface. This interface is validated at build time by TypeScript and pyright/mypy and at runtime by Pydantic.\n\nYou can see a simple demo of an application built with FastUI [here](https://fastui-demo.onrender.com).\n\n## The Practice - Installation\n\nFastUI is made up of 4 things:\n\n- [`fastui` PyPI package](https://pypi.python.org/pypi/fastui) — Pydantic models for UI components, and some utilities. While it works well with [FastAPI](https://fastapi.tiangolo.com) it doesn't depend on FastAPI, and most of it could be used with any python web framework.\n- [`@pydantic/fastui` npm package](https://www.npmjs.com/package/@pydantic/fastui) — a React TypeScript package that lets you reuse the machinery and types of FastUI while implementing your own components\n- [`@pydantic/fastui-bootstrap` npm package](https://www.npmjs.com/package/@pydantic/fastui-bootstrap) — implementation/customisation of all FastUI components using [Bootstrap](https://getbootstrap.com)\n- [`@pydantic/fastui-prebuilt` npm package](https://www.jsdelivr.com/package/npm/@pydantic/fastui-prebuilt) (available on [jsdelivr.com CDN](https://www.jsdelivr.com/package/npm/@pydantic/fastui-prebuilt)) providing a pre-built version of the FastUI React app so you can use it without installing any npm packages or building anything yourself. The Python package provides a simple HTML page to serve this app.\n\n## Usage\n\nHere's a simple but complete FastAPI application that uses FastUI to show some user profiles:\n\n```python\nfrom datetime import date\n\nfrom fastapi import FastAPI, HTTPException\nfrom fastapi.responses import HTMLResponse\nfrom fastui import FastUI, AnyComponent, prebuilt_html, components as c\nfrom fastui.components.display import DisplayMode, DisplayLookup\nfrom fastui.events import GoToEvent, BackEvent\nfrom pydantic import BaseModel, Field\n\napp = FastAPI()\n\n\nclass User(BaseModel):\n    id: int\n    name: str\n    dob: date = Field(title='Date of Birth')\n\n\n# define some users\nusers = [\n    User(id=1, name='John', dob=date(1990, 1, 1)),\n    User(id=2, name='Jack', dob=date(1991, 1, 1)),\n    User(id=3, name='Jill', dob=date(1992, 1, 1)),\n    User(id=4, name='Jane', dob=date(1993, 1, 1)),\n]\n\n\n@app.get(\"/api/\", response_model=FastUI, response_model_exclude_none=True)\ndef users_table() -> list[AnyComponent]:\n    \"\"\"\n    Show a table of four users, `/api` is the endpoint the frontend will connect to\n    when a user visits `/` to fetch components to render.\n    \"\"\"\n    return [\n        c.Page(  # Page provides a basic container for components\n            components=[\n                c.Heading(text='Users', level=2),  # renders `<h2>Users</h2>`\n                c.Table(\n                    data=users,\n                    # define two columns for the table\n                    columns=[\n                        # the first is the users, name rendered as a link to their profile\n                        DisplayLookup(field='name', on_click=GoToEvent(url='/user/{id}/')),\n                        # the second is the date of birth, rendered as a date\n                        DisplayLookup(field='dob', mode=DisplayMode.date),\n                    ],\n                ),\n            ]\n        ),\n    ]\n\n\n@app.get(\"/api/user/{user_id}/\", response_model=FastUI, response_model_exclude_none=True)\ndef user_profile(user_id: int) -> list[AnyComponent]:\n    \"\"\"\n    User profile page, the frontend will fetch this when the user visits `/user/{id}/`.\n    \"\"\"\n    try:\n        user = next(u for u in users if u.id == user_id)\n    except StopIteration:\n        raise HTTPException(status_code=404, detail=\"User not found\")\n    return [\n        c.Page(\n            components=[\n                c.Heading(text=user.name, level=2),\n                c.Link(components=[c.Text(text='Back')], on_click=BackEvent()),\n                c.Details(data=user),\n            ]\n        ),\n    ]\n\n\n@app.get('/{path:path}')\nasync def html_landing() -> HTMLResponse:\n    \"\"\"Simple HTML page which serves the React app, comes last as it matches all paths.\"\"\"\n    return HTMLResponse(prebuilt_html(title='FastUI Demo'))\n```\n\nWhich renders like this:\n\n![screenshot](https://raw.githubusercontent.com/pydantic/FastUI/main/screenshot.png)\n\nOf course, that's a very simple application, the [full demo](https://fastui-demo.onrender.com) is more complete.\n\n### The Principle (long version)\n\nFastUI is an implementation of the RESTful principle; but not as it's usually understood, instead I mean the principle defined in the original [PhD dissertation](https://ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) by Roy Fielding, and excellently summarised in [this essay on htmx.org](https://htmx.org/essays/how-did-rest-come-to-mean-the-opposite-of-rest/) (HTMX people, I'm sorry to use your article to promote React which I know you despise 🙏).\n\nThe RESTful principle as described in the HTMX article is that the frontend doesn't need to (and shouldn't) know anything about the application you're building. Instead, it should just provide all the components you need to construct the interface, the backend can then tell the frontend what to do.\n\nThink of your frontend as a puppet, and the backend as the hand within it — the puppet doesn't need to know what to say, that's kind of the point.\n\nBuilding an application this way has a number of significant advantages:\n\n- You only need to write code in one place to build a new feature — add a new view, change the behavior of an existing view or alter the URL structure\n- Deploying the front and backend can be completely decoupled, provided the frontend knows how to render all the components the backend is going to ask it to use, you're good to go\n- You should be able to reuse a rich set of opensource components, they should end up being better tested and more reliable than anything you could build yourself, this is possible because the components need no context about how they're going to be used (note: since FastUI is brand new, this isn't true yet, hopefully we get there)\n- We can use Pydantic, TypeScript and JSON Schema to provide guarantees that the two sides are communicating with an agreed schema\n\nIn the abstract, FastUI is like the opposite of GraphQL but with the same goal — GraphQL lets frontend developers extend an application without any new backend development; FastUI lets backend developers extend an application without any new frontend development.\n\n#### Beyond Python and React\n\nOf course, this principle shouldn't be limited to Python and React applications — provided we use the same set of agreed schemas and encoding to communicate, we should be able to use any frontend and backend that implements the schema. Interchangeably.\n\nThis could mean:\n\n- Implementing a web frontend using another JS framework like Vue — lots of work, limited value\n- Implementing a web frontend using an edge server, so the browser just sees HTML — lots of work but very valuable\n- Implementing frontends for other platforms like mobile or IOT — lots of work, no idea if it's actually a good idea?\n- Implementing the component models in another language like Rust or Go — since there's actually not that much code in the backend, so this would be a relatively small and mechanical task\n"
  },
  {
    "path": "docs/plugins.py",
    "content": "import os\nimport re\n\nfrom typing import Match\n\nfrom mkdocs.config import Config\nfrom mkdocs.structure.files import Files\nfrom mkdocs.structure.pages import Page\n\ntry:\n    import pytest\nexcept ImportError:\n    pytest = None\n\n\ndef on_pre_build(config: Config):\n    pass\n\n\ndef on_files(files: Files, config: Config) -> Files:\n    return remove_files(files)\n\n\ndef remove_files(files: Files) -> Files:\n    to_remove = []\n    for file in files:\n        if file.src_path in {'plugins.py'}:\n            to_remove.append(file)\n        elif file.src_path.startswith('__pycache__/'):\n            to_remove.append(file)\n\n    for f in to_remove:\n        files.remove(f)\n\n    return files\n\n\ndef on_page_markdown(markdown: str, page: Page, config: Config, files: Files) -> str:\n    markdown = remove_code_fence_attributes(markdown)\n    return add_version(markdown, page)\n\n\ndef add_version(markdown: str, page: Page) -> str:\n    if page.file.src_uri == 'index.md':\n        version_ref = os.getenv('GITHUB_REF')\n        if version_ref and version_ref.startswith('refs/tags/'):\n            version = re.sub('^refs/tags/', '', version_ref.lower())\n            url = f'https://github.com/pydantic/FastUI/releases/tag/{version}'\n            version_str = f'Documentation for version: [{version}]({url})'\n        elif sha := os.getenv('GITHUB_SHA'):\n            sha = sha[:7]\n            url = f'https://github.com/pydantic/FastUI/commit/{sha}'\n            version_str = f'Documentation for development version: [{sha}]({url})'\n        else:\n            version_str = 'Documentation for development version'\n        markdown = re.sub(r'{{ *version *}}', version_str, markdown)\n    return markdown\n\n\ndef remove_code_fence_attributes(markdown: str) -> str:\n    \"\"\"\n    There's no way to add attributes to code fences that works with both pycharm and mkdocs, hence we use\n    `py key=\"value\"` to provide attributes to pytest-examples, then remove those attributes here.\n\n    https://youtrack.jetbrains.com/issue/IDEA-297873 & https://python-markdown.github.io/extensions/fenced_code_blocks/\n    \"\"\"\n\n    def remove_attrs(match: Match[str]) -> str:\n        suffix = re.sub(\n            r' (?:test|lint|upgrade|group|requires|output|rewrite_assert)=\".+?\"', '', match.group(2), flags=re.M\n        )\n        return f'{match.group(1)}{suffix}'\n\n    return re.sub(r'^( *``` *py)(.*)', remove_attrs, markdown, flags=re.M)\n"
  },
  {
    "path": "mkdocs.yml",
    "content": "site_name: FastUI\nsite_description: Build web application user interfaces defined by declarative Python code.\nsite_url: https://docs.pydantic.dev/fastui/\n\ntheme:\n  name: 'material'\n  palette:\n  - media: \"(prefers-color-scheme: light)\"\n    scheme: default\n    primary: pink\n    accent: pink\n    toggle:\n      icon: material/lightbulb-outline\n      name: \"Switch to dark mode\"\n  - media: \"(prefers-color-scheme: dark)\"\n    scheme: slate\n    primary: pink\n    accent: pink\n    toggle:\n      icon: material/lightbulb\n      name: \"Switch to light mode\"\n  features:\n    - content.code.annotate\n    - content.tabs.link\n    - content.code.copy\n    - announce.dismiss\n    - navigation.tabs\n    - search.suggest\n    - search.highlight\n  logo: assets/logo-white.svg\n  favicon: assets/favicon.png\n\nrepo_name: pydantic/FastUI\nrepo_url: https://github.com/pydantic/FastUI\nedit_uri: ''\n\n# https://www.mkdocs.org/user-guide/configuration/#validation\nvalidation:\n  omitted_files: warn\n  absolute_links: warn\n  unrecognized_links: warn\n\nextra_css:\n  - 'extra/tweaks.css'\n\n# TODO: add flarelytics support\n# extra_javascript:\n#   - '/flarelytics/client.js'\n\nmarkdown_extensions:\n  - toc:\n      permalink: true\n  - admonition\n  - pymdownx.details\n  - pymdownx.extra\n  - pymdownx.superfences\n  - pymdownx.highlight:\n      anchor_linenums: true\n  - pymdownx.inlinehilite\n  - pymdownx.snippets\n  - attr_list\n  - md_in_html\n  - pymdownx.emoji:\n      emoji_index: !!python/name:material.extensions.emoji.twemoji\n      emoji_generator: !!python/name:material.extensions.emoji.to_svg\nwatch:\n  - src\nplugins:\n  - search\n  - mkdocstrings:\n      handlers:\n        python:\n          paths:\n            - src/python-fastui\n          options:\n            members_order: source\n            separate_signature: true\n            docstring_options:\n              ignore_init_summary: true\n            merge_init_into_class: true\n            show_signature_annotations: true\n            signature_crossrefs: true\n  - mkdocs-simple-hooks:\n      hooks:\n        on_pre_build: 'docs.plugins:on_pre_build'\n        on_files: 'docs.plugins:on_files'\n        on_page_markdown: 'docs.plugins:on_page_markdown'\nnav:\n  - Introduction: index.md\n  - Guide: guide.md\n  - API Documentation:\n    - Python Components: api/python_components.md\n    - TypeScript Components: api/typescript_components.md\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"FastUI\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"workspaces\": [\n    \"src/*\"\n  ],\n  \"scripts\": {\n    \"dev\": \"npm run --workspace=@pydantic/fastui-prebuilt dev\",\n    \"build\": \"npm run --workspaces prepublishOnly\",\n    \"typecheck\": \"npm run --workspaces typecheck\",\n    \"lint\": \"eslint src --ext .ts,.tsx --report-unused-disable-directives --max-warnings 0\",\n    \"lint-fix\": \"npm run lint -- --fix\",\n    \"prettier\": \"prettier --write\",\n    \"format\": \"npm run prettier -- . && npm run lint-fix\",\n    \"generate-json-schema\": \"./src/python-fastui/tests/react-fastui-json-schema.sh\"\n  },\n  \"prettier\": {\n    \"singleQuote\": true,\n    \"semi\": false,\n    \"trailingComma\": \"all\",\n    \"tabWidth\": 2,\n    \"printWidth\": 119,\n    \"bracketSpacing\": true\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^20.9.1\",\n    \"@types/react\": \"^18.2.15\",\n    \"@types/react-dom\": \"^18.2.7\",\n    \"@typescript-eslint/eslint-plugin\": \"^6.0.0\",\n    \"@typescript-eslint/parser\": \"^6.0.0\",\n    \"eslint\": \"^8.53.0\",\n    \"eslint-config-prettier\": \"^9.0.0\",\n    \"eslint-config-standard\": \"^17.1.0\",\n    \"eslint-plugin-react\": \"^7.33.2\",\n    \"eslint-plugin-react-hooks\": \"^4.6.0\",\n    \"eslint-plugin-react-refresh\": \"^0.4.4\",\n    \"eslint-plugin-simple-import-sort\": \"^10.0.0\",\n    \"json-schema-to-typescript\": \"^15.0.4\",\n    \"typescript\": \"^5.0.2\"\n  },\n  \"dependencies\": {\n    \"prettier\": \"^3.2.5\",\n    \"typedoc\": \"^0.25.13\"\n  }\n}\n"
  },
  {
    "path": "pyproject.toml",
    "content": "# this is not the used for the python package \"fastui\",\n# for that see packages/python-fastui/pyproject.toml\n\n[tool.ruff]\nline-length = 120\nextend-select = [\"Q\", \"RUF100\", \"UP\", \"I\"]\nflake8-quotes = {inline-quotes = \"single\", multiline-quotes = \"double\"}\nformat.quote-style=\"single\"\ntarget-version = \"py310\"\n\n[tool.pyright]\ninclude = [\"src/python-fastui/fastui\"]\n\n[tool.pytest.ini_options]\ntestpaths = [\n    \"src/python-fastui/tests\",\n    \"demo/tests.py\",\n]\nxfail_strict = true\nfilterwarnings = [\"error\"]\nasyncio_mode = \"auto\"\n\n[tool.coverage.run]\nsource = [\"src/python-fastui/fastui\"]\nomit = [\n    \"src/python-fastui/fastui/__main__.py\",\n    \"src/python-fastui/fastui/generate_typescript.py\",\n]\n\n[tool.coverage.report]\nprecision = 2\nexclude_lines = [\n    'pragma: no cover',\n    'raise NotImplementedError',\n    'if TYPE_CHECKING:',\n    'if typing.TYPE_CHECKING:',\n    '@overload',\n    '@typing.overload',\n    '\\(Protocol\\):$',\n]\n"
  },
  {
    "path": "requirements/docs.in",
    "content": "mkdocs\nmkdocs-material\nmkdocs-simple-hooks\nmkdocstrings[python]\nmkdocs-redirects\nmkdocs-material-extensions\n"
  },
  {
    "path": "requirements/docs.txt",
    "content": "#\n# This file is autogenerated by pip-compile with Python 3.11\n# by the following command:\n#\n#    pip-compile --output-file=requirements/docs.txt requirements/docs.in\n#\nbabel==2.14.0\n    # via mkdocs-material\ncertifi==2024.2.2\n    # via requests\ncharset-normalizer==3.3.2\n    # via requests\nclick==8.1.7\n    # via\n    #   mkdocs\n    #   mkdocstrings\ncolorama==0.4.6\n    # via\n    #   griffe\n    #   mkdocs-material\nghp-import==2.1.0\n    # via mkdocs\ngriffe==0.44.0\n    # via mkdocstrings-python\nidna==3.7\n    # via requests\njinja2==3.1.3\n    # via\n    #   mkdocs\n    #   mkdocs-material\n    #   mkdocstrings\nmarkdown==3.6\n    # via\n    #   mkdocs\n    #   mkdocs-autorefs\n    #   mkdocs-material\n    #   mkdocstrings\n    #   pymdown-extensions\nmarkupsafe==2.1.5\n    # via\n    #   jinja2\n    #   mkdocs\n    #   mkdocs-autorefs\n    #   mkdocstrings\nmergedeep==1.3.4\n    # via mkdocs\nmkdocs==1.5.3\n    # via\n    #   -r requirements/docs.in\n    #   mkdocs-autorefs\n    #   mkdocs-material\n    #   mkdocs-redirects\n    #   mkdocs-simple-hooks\n    #   mkdocstrings\nmkdocs-autorefs==1.0.1\n    # via mkdocstrings\nmkdocs-material==9.5.18\n    # via -r requirements/docs.in\nmkdocs-material-extensions==1.3.1\n    # via\n    #   -r requirements/docs.in\n    #   mkdocs-material\nmkdocs-redirects==1.2.1\n    # via -r requirements/docs.in\nmkdocs-simple-hooks==0.1.5\n    # via -r requirements/docs.in\nmkdocstrings[python]==0.24.3\n    # via\n    #   -r requirements/docs.in\n    #   mkdocstrings-python\nmkdocstrings-python==1.10.0\n    # via mkdocstrings\npackaging==24.0\n    # via mkdocs\npaginate==0.5.6\n    # via mkdocs-material\npathspec==0.12.1\n    # via mkdocs\nplatformdirs==4.2.0\n    # via\n    #   mkdocs\n    #   mkdocstrings\npygments==2.17.2\n    # via mkdocs-material\npymdown-extensions==10.8\n    # via\n    #   mkdocs-material\n    #   mkdocstrings\npython-dateutil==2.9.0.post0\n    # via ghp-import\npyyaml==6.0.1\n    # via\n    #   mkdocs\n    #   pymdown-extensions\n    #   pyyaml-env-tag\npyyaml-env-tag==0.1\n    # via mkdocs\nregex==2024.4.16\n    # via mkdocs-material\nrequests==2.31.0\n    # via mkdocs-material\nsix==1.16.0\n    # via python-dateutil\nurllib3==2.2.1\n    # via requests\nwatchdog==4.0.0\n    # via mkdocs\n"
  },
  {
    "path": "src/npm-fastui/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2023 to present Pydantic Services inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "src/npm-fastui/README.md",
    "content": "# FastUI\n\nReact frontend for [FastUI](https://github.com/pydantic/FastUI).\n"
  },
  {
    "path": "src/npm-fastui/package.json",
    "content": "{\n  \"name\": \"@pydantic/fastui\",\n  \"version\": \"0.0.26\",\n  \"description\": \"Build better UIs faster.\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"author\": \"Samuel Colvin\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://github.com/pydantic/fastui\",\n  \"private\": false,\n  \"keywords\": [\n    \"fastui\",\n    \"jsx\",\n    \"typescript\",\n    \"react\",\n    \"fastapi\"\n  ],\n  \"scripts\": {\n    \"prepublishOnly\": \"rm -rf dist && tsc\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"typewatch\": \"tsc --noEmit --watch\"\n  },\n  \"dependencies\": {\n    \"@microsoft/fetch-event-source\": \"^2.0.1\",\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"react-markdown\": \"^9.0.1\",\n    \"react-select\": \"^5.8.0\",\n    \"react-syntax-highlighter\": \"^15.5.0\",\n    \"remark-gfm\": \"^4.0.0\"\n  },\n  \"devDependencies\": {\n    \"@types/react-syntax-highlighter\": \"^15.5.10\"\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/Defaults.tsx",
    "content": "import { FC, ReactNode } from 'react'\n\nexport const DefaultNotFound: FC<{ url: string }> = ({ url }) => <div>Page not found: {url}</div>\n\n// default here does nothing\nexport const DefaultTransition: FC<{ children: ReactNode; transitioning: boolean }> = ({ children }) => (\n  <div>{children}</div>\n)\n"
  },
  {
    "path": "src/npm-fastui/src/components/Code.tsx",
    "content": "import { lazy } from 'react'\n\nexport const CodeComp = lazy(() => import('./CodeLazy'))\n"
  },
  {
    "path": "src/npm-fastui/src/components/CodeLazy.tsx",
    "content": "import * as codeStyles from 'react-syntax-highlighter/dist/esm/styles/prism'\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'\n\nimport type { Code } from '../models'\n\nimport { useClassName } from '../hooks/className'\n\nexport default function (props: Code) {\n  const { text, language, codeStyle } = props\n  const codeLookup = codeStyle as keyof typeof codeStyles\n  const style = (codeStyle && codeStyles[codeLookup]) || codeStyles.coldarkCold\n  return (\n    <SyntaxHighlighter className={useClassName(props)} PreTag=\"div\" language={language} style={style}>\n      {text}\n    </SyntaxHighlighter>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/Custom.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Custom } from '../models'\n\nimport { DisplayError } from '../hooks/error'\n\nimport { JsonComp } from './Json'\n\nexport const CustomComp: FC<Custom> = (props) => {\n  const { data, subType, library } = props\n\n  const description = [`The custom component \"${subType}\"`]\n  if (library) {\n    description.push(`from library \"${library}\"`)\n  }\n  description.push(`has no implementation with this frontend app.`)\n\n  return (\n    <DisplayError title=\"Custom component without implementation\" description={description.join(' ')}>\n      Custom component data:\n      <JsonComp type=\"JSON\" value={data} />\n    </DisplayError>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/FireEvent.tsx",
    "content": "import { FC, useEffect } from 'react'\n\nimport type { FireEvent } from '../models'\n\nimport { useFireEvent } from '../events'\n\nexport const FireEventComp: FC<FireEvent> = ({ event, message }) => {\n  const { fireEvent } = useFireEvent()\n\n  useEffect(() => {\n    // debounce the event so changes to fireEvent (from location changes) don't trigger the event many times\n    const clear = setTimeout(() => fireEvent(event), 50)\n    return () => clearTimeout(clear)\n  }, [fireEvent, event])\n\n  return <>{message}</>\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/FormField.tsx",
    "content": "import { FC, useState } from 'react'\nimport AsyncSelect from 'react-select/async'\nimport Select, { StylesConfig } from 'react-select'\n\nimport type {\n  FormFieldInput,\n  FormFieldTextarea,\n  FormFieldBoolean,\n  FormFieldFile,\n  FormFieldSelect,\n  FormFieldSelectSearch,\n  SelectOption,\n  SelectOptions,\n  SelectGroup,\n} from '../models'\n\nimport { useClassName } from '../hooks/className'\nimport { debounce, useRequest } from '../tools'\n\ntype PrivateOnChange = () => void\n\ninterface FormFieldInputProps extends FormFieldInput {\n  onChange?: PrivateOnChange\n}\n\nexport const FormFieldInputComp: FC<FormFieldInputProps> = (props) => {\n  const { name, placeholder, required, htmlType, locked, autocomplete, onChange } = props\n\n  return (\n    <div className={useClassName(props)}>\n      <Label {...props} />\n      <input\n        type={htmlType}\n        className={useClassName(props, { el: 'input' })}\n        defaultValue={props.initial}\n        id={inputId(props)}\n        name={name}\n        required={required}\n        disabled={locked}\n        placeholder={placeholder}\n        autoComplete={autocomplete}\n        aria-describedby={descId(props)}\n        onChange={onChange}\n      />\n      <ErrorDescription {...props} />\n    </div>\n  )\n}\n\ninterface FormFieldTextareaProps extends FormFieldTextarea {\n  onChange?: PrivateOnChange\n}\n\nexport const FormFieldTextareaComp: FC<FormFieldTextareaProps> = (props) => {\n  const { name, placeholder, required, locked, rows, cols, autocomplete } = props\n  return (\n    <div className={useClassName(props)}>\n      <Label {...props} />\n      <textarea\n        className={useClassName(props, { el: 'textarea' })}\n        defaultValue={props.initial}\n        id={inputId(props)}\n        rows={rows}\n        cols={cols}\n        name={name}\n        required={required}\n        disabled={locked}\n        placeholder={placeholder}\n        aria-describedby={descId(props)}\n        autoComplete={autocomplete}\n      />\n      <ErrorDescription {...props} />\n    </div>\n  )\n}\n\ninterface FormFieldBooleanProps extends FormFieldBoolean {\n  onChange?: PrivateOnChange\n}\n\nexport const FormFieldBooleanComp: FC<FormFieldBooleanProps> = (props) => {\n  const { name, required, locked, onChange } = props\n\n  return (\n    <div className={useClassName(props)}>\n      <Label {...props} />\n      <input\n        type=\"checkbox\"\n        className={useClassName(props, { el: 'input' })}\n        defaultChecked={!!props.initial}\n        id={inputId(props)}\n        name={name}\n        required={required}\n        disabled={locked}\n        aria-describedby={descId(props)}\n        onChange={onChange}\n      />\n      <ErrorDescription {...props} />\n    </div>\n  )\n}\n\ninterface FormFieldFileProps extends FormFieldFile {\n  onChange?: PrivateOnChange\n}\n\nexport const FormFieldFileComp: FC<FormFieldFileProps> = (props) => {\n  const { name, required, locked, multiple, accept } = props\n\n  return (\n    <div className={useClassName(props)}>\n      <Label {...props} />\n      <input\n        type=\"file\"\n        className={useClassName(props, { el: 'input' })}\n        id={inputId(props)}\n        name={name}\n        required={required}\n        disabled={locked}\n        multiple={multiple ?? false}\n        accept={accept}\n      />\n      <ErrorDescription {...props} />\n    </div>\n  )\n}\n\n// cheat slightly and match bootstrap 😱\n// TODO make this configurable as an argument to `FastUI`\nconst styles: StylesConfig = {\n  control: (base) => ({ ...base, borderRadius: '0.375rem', border: '1px solid #dee2e6' }),\n}\n\ninterface FormFieldSelectProps extends FormFieldSelect {\n  onChange?: PrivateOnChange\n}\n\nexport const FormFieldSelectComp: FC<FormFieldSelectProps> = (props) => {\n  if (props.vanilla) {\n    return <FormFieldSelectVanillaComp {...props} />\n  } else {\n    return <FormFieldSelectReactComp {...props} />\n  }\n}\n\nexport const FormFieldSelectVanillaComp: FC<FormFieldSelectProps> = (props) => {\n  const { name, required, locked, options, multiple, initial, placeholder, onChange, autocomplete } = props\n\n  const className = useClassName(props)\n  const classNameSelect = useClassName(props, { el: 'select' })\n  return (\n    <div className={className}>\n      <Label {...props} />\n      <select\n        id={inputId(props)}\n        className={classNameSelect}\n        defaultValue={initial}\n        multiple={multiple}\n        name={name}\n        required={required}\n        disabled={locked}\n        aria-describedby={descId(props)}\n        placeholder={placeholder}\n        onChange={() => onChange && onChange()}\n        autoComplete={autocomplete}\n      >\n        {multiple ? null : <option></option>}\n        {options.map((option, i) => (\n          <SelectOptionComp key={i} option={option} />\n        ))}\n      </select>\n      <ErrorDescription {...props} />\n    </div>\n  )\n}\n\nexport const FormFieldSelectReactComp: FC<FormFieldSelectProps> = (props) => {\n  const { name, required, locked, options, multiple, initial, placeholder, onChange } = props\n\n  const className = useClassName(props)\n  const classNameSelectReact = useClassName(props, { el: 'select-react' })\n  let value\n  if (Array.isArray(initial)) {\n    value = findDefaultArray(options, initial)\n  } else {\n    value = findDefault(options, initial)\n  }\n\n  const reactSelectOnChanged = () => {\n    // TODO this is a hack to wait for the input to be updated, can we do better?\n    setTimeout(() => {\n      onChange && onChange()\n    }, 50)\n  }\n\n  return (\n    <div className={className}>\n      <Label {...props} />\n      <Select\n        id={inputId(props)}\n        classNamePrefix=\"fastui-react-select\"\n        className={classNameSelectReact}\n        isMulti={multiple ?? false}\n        isClearable\n        defaultValue={value}\n        name={name}\n        required={required}\n        isDisabled={locked}\n        options={options}\n        aria-describedby={descId(props)}\n        styles={styles}\n        placeholder={placeholder}\n        onChange={reactSelectOnChanged}\n      />\n      <ErrorDescription {...props} />\n    </div>\n  )\n}\n\nconst SelectOptionComp: FC<{ option: SelectOption | SelectGroup }> = ({ option }) => {\n  if ('options' in option) {\n    return (\n      <optgroup label={option.label}>\n        {option.options.map((o) => (\n          <SelectOptionComp key={o.value} option={o} />\n        ))}\n      </optgroup>\n    )\n  } else {\n    return <option value={option.value}>{option.label}</option>\n  }\n}\n\nfunction findDefaultArray(options: SelectOptions, value: string[]): SelectOption[] {\n  const foundValues = value.map((v) => findDefault(options, v))\n  return foundValues.filter((v) => v) as SelectOption[]\n}\n\nfunction findDefault(options: SelectOptions, value?: string): SelectOption | undefined {\n  for (const option of options) {\n    if ('options' in option) {\n      const found = findDefault(option.options, value)\n      if (found) {\n        return found\n      }\n    } else if (option.value === value) {\n      return option\n    }\n  }\n}\n\ninterface FormFieldSelectSearchProps extends FormFieldSelectSearch {\n  onChange?: PrivateOnChange\n}\n\nexport const FormFieldSelectSearchComp: FC<FormFieldSelectSearchProps> = (props) => {\n  const { name, required, locked, searchUrl, initial, multiple, placeholder, onChange } = props\n  const [isLoading, setIsLoading] = useState(false)\n  const request = useRequest()\n\n  const loadOptions = debounce((inputValue: string, callback: (options: SelectOptions) => void) => {\n    setIsLoading(true)\n    request({\n      url: searchUrl,\n      query: { q: inputValue },\n    })\n      .then(([, response]) => {\n        const { options } = response as { options: SelectOptions }\n        callback(options)\n        setIsLoading(false)\n      })\n      .catch(() => {\n        setIsLoading(false)\n      })\n  }, props.debounce ?? 300)\n\n  const reactSelectOnChanged = () => {\n    // TODO this is a hack to wait for the input to be updated, can we do better?\n    setTimeout(() => {\n      onChange && onChange()\n    }, 50)\n  }\n\n  return (\n    <div className={useClassName(props)}>\n      <Label {...props} />\n      <AsyncSelect\n        classNamePrefix=\"fastui-react-select\"\n        id={inputId(props)}\n        className={useClassName(props, { el: 'select-react' })}\n        isMulti={multiple ?? false}\n        cacheOptions\n        isClearable\n        defaultOptions\n        loadOptions={loadOptions}\n        defaultValue={initial}\n        noOptionsMessage={({ inputValue }) => (inputValue ? 'No results' : 'Type to search')}\n        name={name}\n        required={required}\n        isDisabled={locked}\n        isLoading={isLoading}\n        aria-describedby={descId(props)}\n        styles={styles}\n        placeholder={placeholder}\n        onChange={reactSelectOnChanged}\n      />\n      <ErrorDescription {...props} />\n    </div>\n  )\n}\n\nconst Label: FC<FormFieldProps> = (props) => {\n  let { title } = props\n  if (!Array.isArray(title)) {\n    title = [title]\n  }\n  return (\n    <label htmlFor={inputId(props)} className={useClassName(props, { el: 'label' })}>\n      {title.map((t, i) => (\n        <span key={i}>\n          {i > 0 ? <> &rsaquo;</> : null} {t}\n        </span>\n      ))}\n    </label>\n  )\n}\n\nexport type FormFieldProps =\n  | FormFieldInputProps\n  | FormFieldTextareaProps\n  | FormFieldBooleanProps\n  | FormFieldFileProps\n  | FormFieldSelectProps\n  | FormFieldSelectSearchProps\n\nconst inputId = (props: FormFieldProps) => `form-field-${props.name}`\nconst descId = (props: FormFieldProps) => (props.description ? `${inputId(props)}-desc` : undefined)\n\nconst ErrorDescription: FC<FormFieldProps> = (props) => {\n  const { description, error } = props\n  const descClassName = useClassName(props, { el: 'description' })\n  const errorClassName = useClassName(props, { el: 'error' })\n  return (\n    <>\n      {description ? (\n        <div id={descId(props)} className={descClassName}>\n          {description}\n        </div>\n      ) : null}\n      {error ? <div className={errorClassName}>{error}</div> : null}\n    </>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/Iframe.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Iframe } from '../models'\n\nexport const IframeComp: FC<Iframe> = (props) => {\n  const { src, width, height, title, sandbox, srcdoc } = props\n  return <iframe src={src} width={width} height={height} title={title} sandbox={sandbox} srcDoc={srcdoc} />\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/Json.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Json } from '../models'\n\nimport { CodeComp } from './Code'\n\nexport const JsonComp: FC<Json> = (props) => {\n  let { value, className } = props\n  // if the value is a string, we assume it's already JSON, and parse it\n  if (typeof value === 'string') {\n    try {\n      value = JSON.parse(value)\n    } catch (e) {\n      // if it's not valid JSON, we just display it as a string\n    }\n  }\n  return <CodeComp type=\"Code\" text={JSON.stringify(value, null, 2)} language=\"json\" className={className} />\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/LinkList.tsx",
    "content": "import type { LinkList } from '../models'\n\nimport { useClassName } from '../hooks/className'\n\nimport { LinkComp } from './link'\n\nexport const LinkListComp = (props: LinkList) => {\n  const itemClassName = useClassName(props, { el: 'link-list-item' })\n  return (\n    <div className={useClassName(props)}>\n      {props.links.map((link, i) => (\n        <div key={i} className={itemClassName}>\n          <LinkComp {...{ ...link, mode: props.mode }} />\n        </div>\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/Markdown.tsx",
    "content": "import { lazy } from 'react'\n\nexport const MarkdownComp = lazy(() => import('./MarkdownLazy'))\n"
  },
  {
    "path": "src/npm-fastui/src/components/MarkdownLazy.tsx",
    "content": "import { FC, MouseEventHandler, ReactNode } from 'react'\nimport ReactMarkdown, { Components } from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nimport type { Markdown, Code, AnyEvent } from '../models'\n\nimport { useClassName } from '../hooks/className'\nimport { useFireEvent } from '../events'\nimport { useCustomRender } from '../hooks/config'\n\nimport { CodeComp } from './Code'\n\nconst MarkdownComp: FC<Markdown> = (props) => {\n  const { text, codeStyle } = props\n  const components: Components = {\n    a({ children, href }) {\n      return <MarkdownA href={href}>{children}</MarkdownA>\n    },\n    code({ children, className }) {\n      return (\n        <MarkdownCode className={className} codeStyle={codeStyle}>\n          {children}\n        </MarkdownCode>\n      )\n    },\n  }\n\n  return (\n    <ReactMarkdown\n      className={useClassName(props, { dft: 'fastui-markdown' })}\n      remarkPlugins={[remarkGfm]}\n      components={components}\n    >\n      {text}\n    </ReactMarkdown>\n  )\n}\n\nexport default MarkdownComp\n\nconst MarkdownA: FC<{ children: ReactNode; href?: string }> = ({ children, href }) => {\n  const { fireEvent } = useFireEvent()\n\n  let onClick: AnyEvent | undefined\n  let preventDefault = true\n  if (!href) {\n    href = '#'\n  } else if (href === '!back') {\n    href = '#'\n    onClick = { type: 'back' }\n  } else if (href.startsWith('!')) {\n    onClick = { type: 'page', name: href.slice(1) }\n    href = '#'\n  } else if (href.startsWith('#')) {\n    preventDefault = href.length === 1\n  } else {\n    onClick = { type: 'go-to', url: href }\n  }\n\n  const clickHandler: MouseEventHandler<HTMLAnchorElement> = (e) => {\n    if (preventDefault) {\n      e.preventDefault()\n      fireEvent(onClick)\n    }\n  }\n\n  return (\n    <a href={href} onClick={clickHandler}>\n      {children}\n    </a>\n  )\n}\n\ninterface MarkdownCodeProps {\n  children: ReactNode\n  className?: string\n  codeStyle?: string\n}\n\nconst MarkdownCode: FC<MarkdownCodeProps> = ({ children, className, codeStyle }) => {\n  const match = /language-(\\w+)/.exec(className || '')\n  if (match) {\n    return (\n      <MarkdownCodeHighlight codeStyle={codeStyle} language={match[1]}>\n        {children}\n      </MarkdownCodeHighlight>\n    )\n  } else {\n    return <code className={className}>{children}</code>\n  }\n}\n\ninterface MarkdownCodeHighlightProps {\n  children: ReactNode\n  language?: string\n  codeStyle?: string\n}\n\nconst MarkdownCodeHighlight: FC<MarkdownCodeHighlightProps> = ({ children, codeStyle, language }) => {\n  const codeProps: Code = {\n    type: 'Code',\n    text: String(children).replace(/\\n$/, ''),\n    language,\n    codeStyle,\n  }\n  const CustomRenderComp = useCustomRender(codeProps)\n  if (CustomRenderComp) {\n    return <CustomRenderComp />\n  } else {\n    return <CodeComp {...codeProps} />\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/PageTitle.tsx",
    "content": "import { FC, useEffect } from 'react'\n\nimport type { PageTitle } from '../models'\n\nexport const PageTitleComp: FC<PageTitle> = (props) => {\n  const { text } = props\n\n  useEffect(() => {\n    document.title = text\n  }, [text])\n\n  return <></>\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/ServerLoad.tsx",
    "content": "import { FC, useCallback, useContext, useEffect, useState } from 'react'\n\nimport type { ServerLoad, PageEvent, FastProps } from '../models'\n\nimport { ErrorContext } from '../hooks/error'\nimport { useRequest, useSSE, Method } from '../tools'\nimport { DefaultNotFound, DefaultTransition } from '../Defaults'\nimport { ConfigContext } from '../hooks/config'\nimport { usePageEventListen } from '../events'\nimport { EventContextProvider, useEventContext } from '../hooks/eventContext'\nimport { LocationContext } from '../hooks/locationContext'\n\nimport { AnyCompList } from './index'\n\nimport { SpinnerComp } from './spinner'\n\nexport const ServerLoadComp: FC<ServerLoad> = (props) => {\n  const { path, components, loadTrigger, sse, method, sseRetry } = props\n  if (components) {\n    return (\n      <ServerLoadDefer\n        path={path}\n        components={components}\n        loadTrigger={loadTrigger}\n        sse={sse}\n        method={method}\n        sseRetry={sseRetry}\n      />\n    )\n  } else if (sse) {\n    return <ServerLoadSSE path={path} method={method} sseRetry={sseRetry} />\n  } else {\n    return <ServerLoadFetch path={path} />\n  }\n}\n\ninterface DeferProps {\n  path: string\n  components: FastProps[]\n  loadTrigger?: PageEvent\n  sse?: boolean\n  method?: Method\n  sseRetry?: number\n}\n\nconst ServerLoadDefer: FC<DeferProps> = ({ components, path, loadTrigger, sse, method, sseRetry }) => {\n  const { eventContext } = usePageEventListen(loadTrigger)\n\n  if (eventContext) {\n    return (\n      <EventContextProvider context={eventContext}>\n        {sse ? (\n          <ServerLoadSSE path={path} method={method} sseRetry={sseRetry} />\n        ) : (\n          <ServerLoadFetch path={path} method={method} />\n        )}\n      </EventContextProvider>\n    )\n  } else {\n    return <AnyCompList propsList={components} />\n  }\n}\n\ninterface FetchProps {\n  path: string\n  devReload?: number\n  method?: Method\n}\n\nexport const ServerLoadFetch: FC<FetchProps> = ({ path, devReload, method }) => {\n  const [transitioning, setTransitioning] = useState<boolean>(false)\n  const [componentProps, setComponentProps] = useState<FastProps[] | null>(null)\n  const [notFoundUrl, setNotFoundUrl] = useState<string | undefined>(undefined)\n\n  const { fullPath } = useContext(LocationContext)\n  const url = useServerUrl(path)\n  const request = useRequest()\n\n  useEffect(() => {\n    setTransitioning(true)\n    let componentLoaded = true\n    request({ url, method, expectedStatus: [200, 345, 404] }).then(([status, data]) => {\n      if (componentLoaded) {\n        // 345 is treat the same as 200 - the server is expected to return valid FastUI components\n        if (status === 200 || status === 345) {\n          setComponentProps(data as FastProps[])\n          // if there's a fragment, scroll to that ID once the page is loaded\n          const fragment = getFragment(path)\n          if (fragment) {\n            setTimeout(() => {\n              const element = document.getElementById(fragment)\n              if (element) {\n                element.scrollIntoView()\n              }\n            }, 50)\n          }\n        } else {\n          setNotFoundUrl(url)\n        }\n      }\n      setTransitioning(false)\n    })\n\n    return () => {\n      componentLoaded = false\n    }\n  }, [url, path, request, devReload, method])\n\n  useEffect(() => {\n    setNotFoundUrl(undefined)\n  }, [fullPath])\n\n  return <Render propsList={componentProps} notFoundUrl={notFoundUrl} transitioning={transitioning} />\n}\n\ninterface SSEProps {\n  path: string\n  method?: Method\n  sseRetry?: number\n}\n\nexport const ServerLoadSSE: FC<SSEProps> = ({ path, method, sseRetry }) => {\n  const [componentProps, setComponentProps] = useState<FastProps[] | null>(null)\n\n  const url = useServerUrl(path)\n  const onMessage = useCallback((data: any) => setComponentProps(data as FastProps[]), [])\n  useSSE(url, onMessage, method, sseRetry)\n\n  return <Render propsList={componentProps} transitioning={false} />\n}\n\nconst Render: FC<{ propsList: FastProps[] | null; notFoundUrl?: string; transitioning: boolean }> = ({\n  propsList,\n  notFoundUrl,\n  transitioning,\n}) => {\n  const { error } = useContext(ErrorContext)\n  const { NotFound, Transition } = useContext(ConfigContext)\n  const NotFoundComp = NotFound ?? DefaultNotFound\n  const TransitionComp = Transition ?? DefaultTransition\n\n  if (notFoundUrl) {\n    return <NotFoundComp url={notFoundUrl} />\n  } else if (propsList === null) {\n    if (error) {\n      return <></>\n    } else {\n      return <SpinnerComp type=\"Spinner\" />\n    }\n  } else {\n    return (\n      <TransitionComp transitioning={transitioning}>\n        <AnyCompList propsList={propsList} />\n      </TransitionComp>\n    )\n  }\n}\n\nfunction useServerUrl(path: string): string {\n  const { APIRootUrl, APIPathMode, APIPathStrip } = useContext(ConfigContext)\n  if (APIPathStrip && path.startsWith(APIPathStrip)) {\n    path = path.slice(APIPathStrip.length)\n  }\n  const applyContext = useEventContext()\n  const requestPath = applyContext(path)\n\n  if (APIPathMode === 'query') {\n    return `${APIRootUrl}?path=${encodeURIComponent(requestPath)}`\n  } else {\n    return APIRootUrl + requestPath\n  }\n}\n\nfunction getFragment(path: string): string | undefined {\n  const index = path.indexOf('#')\n  if (index !== -1) {\n    return path.slice(index + 1)\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/button.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Button } from '../models'\n\nimport { useClassName } from '../hooks/className'\nimport { useFireEvent } from '../events'\n\nexport const ButtonComp: FC<Button> = (props) => {\n  const { text, onClick, htmlType } = props\n\n  const { fireEvent } = useFireEvent()\n\n  return (\n    <button className={useClassName(props)} type={htmlType} onClick={() => fireEvent(onClick)}>\n      {text}\n    </button>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/details.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Details, Display, DisplayMode } from '../models'\n\nimport { asTitle } from '../tools'\nimport { useClassName } from '../hooks/className'\n\nimport { DisplayComp, DisplayLookupProps, renderEvent } from './display'\n\nexport const DetailsComp: FC<Details> = (props) => (\n  <dl className={useClassName(props)}>\n    {props.fields.map((field, id) => (\n      <FieldDetail key={id} props={props} fieldDisplay={field} />\n    ))}\n  </dl>\n)\n\nconst FieldDetail: FC<{ props: Details; fieldDisplay: DisplayLookupProps | Display }> = ({ props, fieldDisplay }) => {\n  const onClick = fieldDisplay.onClick\n  let title = fieldDisplay.title\n  const rest: { mode?: DisplayMode; tableWidthPercent?: number } = { mode: fieldDisplay.mode }\n  let value: any\n\n  if ('type' in fieldDisplay && fieldDisplay.type === 'Display') {\n    // fieldDisplay is Display\n    value = fieldDisplay.value\n  } else if ('field' in fieldDisplay) {\n    // fieldDisplay is DisplayLookupProps\n    const field = fieldDisplay.field\n    title = title ?? asTitle(field)\n    value = props.data[field]\n    rest.tableWidthPercent = fieldDisplay.tableWidthPercent\n  }\n  const renderedOnClick = renderEvent(onClick, props.data)\n  return (\n    <>\n      <dt className={useClassName(props, { el: 'dt' })}>{title}</dt>\n      <dd className={useClassName(props, { el: 'dd' })}>\n        <DisplayComp type=\"Display\" onClick={renderedOnClick} value={value !== undefined ? value : null} {...rest} />\n      </dd>\n    </>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/display.tsx",
    "content": "import { FC } from 'react'\n\nimport type { AnyEvent, DisplayMode, Display, JsonData, FastProps } from '../models'\n\nimport { useCustomRender } from '../hooks/config'\nimport { unreachable, asTitle } from '../tools'\n\nimport { AnyComp } from '.'\n\nimport { JsonComp } from './Json'\nimport { LinkRender } from './link'\nimport MarkdownComp from './MarkdownLazy'\n\nexport const DisplayComp: FC<Display> = (props) => {\n  const CustomRenderComp = useCustomRender(props)\n  if (CustomRenderComp) {\n    return <CustomRenderComp />\n  }\n\n  const { onClick } = props\n  if (onClick) {\n    return (\n      <LinkRender onClick={onClick}>\n        <DisplayRender {...props} />\n      </LinkRender>\n    )\n  } else {\n    return <DisplayRender {...props} />\n  }\n}\n\n// todo: this list should probably be defined in the models file\nconst nestableSubcomponents = [\n  'Text',\n  'Paragraph',\n  'Div',\n  'Heading',\n  'Markdown',\n  'Code',\n  'Json',\n  'Button',\n  'Link',\n  'LinkList',\n  'ServerLoad',\n  'Image',\n  'Iframe',\n  'Video',\n  'Spinner',\n  'Custom',\n  'Table',\n  'Details',\n]\n\nconst DisplayRender: FC<Display> = (props) => {\n  const mode = props.mode ?? 'auto'\n  const value = props.value ?? null\n  if (mode === 'json') {\n    return <JsonComp type=\"JSON\" value={value} />\n  } else if (Array.isArray(value)) {\n    return <DisplayArray mode={mode} value={value} />\n  } else if (typeof value === 'object' && value !== null) {\n    if (value.type !== null && typeof value.type === 'string' && nestableSubcomponents.includes(value.type)) {\n      return <AnyComp {...(value as unknown as FastProps)} />\n    } else {\n      return <DisplayObject mode={mode} value={value} />\n    }\n  } else {\n    return <DisplayPrimitive mode={mode} value={value} />\n  }\n}\n\ninterface DisplayArrayProps {\n  value: JsonData[]\n  mode?: DisplayMode\n}\n\nexport const DisplayArray: FC<DisplayArrayProps> = (props) => {\n  const { mode, value } = props\n\n  return (\n    <>\n      {value.map((v, i) => (\n        <span key={i}>\n          <DisplayComp type=\"Display\" mode={mode} value={v} />,{' '}\n        </span>\n      ))}\n    </>\n  )\n}\n\ninterface DisplayObjectProps {\n  value: { [key: string]: JsonData }\n  mode?: DisplayMode\n}\n\nexport const DisplayObject: FC<DisplayObjectProps> = (props) => {\n  const { mode, value } = props\n\n  return (\n    <>\n      {Object.entries(value).map(([key, v], i) => (\n        <span key={key}>\n          {key}: <DisplayComp type=\"Display\" mode={mode} key={i} value={v} />,{' '}\n        </span>\n      ))}\n    </>\n  )\n}\n\ntype JSONPrimitive = string | number | boolean | null\n\nexport interface DisplayPrimitiveProps {\n  value: JSONPrimitive\n  mode: DisplayMode\n}\n\nexport const DisplayPrimitive: FC<DisplayPrimitiveProps> = (props) => {\n  const { mode, value } = props\n\n  switch (mode) {\n    case 'auto':\n      return <DisplayAuto value={value} />\n    case 'plain':\n      return <DisplayPlain value={value} />\n    case 'datetime':\n      return <DisplayDateTime value={value} />\n    case 'date':\n      return <DisplayDate value={value} />\n    case 'duration':\n      return <DisplayDuration value={value} />\n    case 'as_title':\n      return <DisplayAsTitle value={value} />\n    case 'markdown':\n      return <DisplayMarkdown value={value} />\n    case 'json':\n    case 'inline_code':\n      return <DisplayInlineCode value={value} />\n    case 'currency':\n      return <DisplayCurrency value={value} />\n    default:\n      unreachable('Unexpected display type', mode, props)\n  }\n}\n\nconst DisplayNull: FC = () => {\n  return <span className=\"fu-null\">&mdash;</span>\n}\n\nconst DisplayAuto: FC<{ value: JSONPrimitive }> = ({ value }) => {\n  if (value === null) {\n    return <DisplayNull />\n  } else if (typeof value === 'boolean') {\n    if (value) {\n      return <>✓</>\n    } else {\n      return <>&times;</>\n    }\n  } else if (typeof value === 'number') {\n    return <>{value.toLocaleString()}</>\n  } else {\n    return <>{value}</>\n  }\n}\n\nconst DisplayPlain: FC<{ value: JSONPrimitive }> = ({ value }) => {\n  if (value === null) {\n    return <DisplayNull />\n  } else {\n    return <>{value.toString()}</>\n  }\n}\n\nconst DisplayDateTime: FC<{ value: JSONPrimitive }> = ({ value }) => {\n  if (value === null) {\n    return <DisplayNull />\n  } else {\n    // TODO\n    return <>{value.toString()}</>\n  }\n}\n\nconst DisplayDate: FC<{ value: JSONPrimitive }> = ({ value }) => {\n  if (value === null) {\n    return <DisplayNull />\n  } else {\n    // TODO\n    return <>{value.toString()}</>\n  }\n}\n\nconst DisplayDuration: FC<{ value: JSONPrimitive }> = ({ value }) => {\n  if (value === null) {\n    return <DisplayNull />\n  } else {\n    // TODO\n    return <>{value.toString()}</>\n  }\n}\n\nconst DisplayAsTitle: FC<{ value: JSONPrimitive }> = ({ value }) => {\n  if (value === null) {\n    return <DisplayNull />\n  } else {\n    return <>{asTitle(value.toString())}</>\n  }\n}\n\nconst DisplayMarkdown: FC<{ value: JSONPrimitive }> = ({ value }) => {\n  if (value === null) {\n    return <DisplayNull />\n  } else {\n    return <MarkdownComp text={value.toString()} type=\"Markdown\" />\n  }\n}\n\nconst DisplayInlineCode: FC<{ value: JSONPrimitive }> = ({ value }) => {\n  if (value === null) {\n    return <DisplayNull />\n  } else {\n    return <code className=\"fu-inline-code\">{value.toString()}</code>\n  }\n}\n\nconst DisplayCurrency: FC<{ value: JSONPrimitive }> = ({ value }) => {\n  if (typeof value === 'boolean') {\n    return value.toString()\n  } else if (value === null) {\n    return <DisplayNull />\n  } else {\n    return Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(\n      typeof value === 'string' ? parseFloat(value) : value,\n    )\n  }\n}\n\nexport type DataModel = Record<string, JsonData>\n\nexport interface DisplayLookupProps extends Omit<Display, 'type' | 'value'> {\n  field: string\n  tableWidthPercent?: number\n}\n\nexport function renderEvent(event: AnyEvent | undefined, data: DataModel): AnyEvent | undefined {\n  let newEvent: AnyEvent | undefined = event ? { ...event } : undefined\n  if (newEvent) {\n    if (newEvent.type === 'go-to' && newEvent.url) {\n      // for go-to events with a URL, substitute the row values into the url\n      let url: string | null = null\n      try {\n        url = subKeys(newEvent.url, data)\n      } catch (e) {\n        url = null\n      }\n      if (url === null) {\n        newEvent = undefined\n      } else {\n        newEvent.url = url\n      }\n    }\n  }\n  return newEvent\n}\n\nconst subKeys = (template: string, row: DataModel): string | null => {\n  let returnNull = false\n  const r = template.replace(/{(.+?)}/g, (_, key: string): string => {\n    const v: JsonData | undefined = row[key]\n    if (v === undefined) {\n      throw new Error(`field \"${key}\" not found in ${JSON.stringify(row)}`)\n    } else if (v === null) {\n      returnNull = true\n      return 'null'\n    } else {\n      return v.toString()\n    }\n  })\n  if (returnNull) {\n    return null\n  } else {\n    return r\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/div.tsx",
    "content": "import { FC } from 'react'\n\nimport { Div, Page } from '../models'\nimport { useClassName } from '../hooks/className'\n\nimport { AnyCompList } from './index'\n\nexport const DivComp: FC<Div | Page> = (props) => (\n  <div className={useClassName(props)}>\n    <AnyCompList propsList={props.components} />\n  </div>\n)\n"
  },
  {
    "path": "src/npm-fastui/src/components/error.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Error } from '../models'\n\nimport { useClassName } from '../hooks/className'\n\nexport const ErrorComp: FC<Error> = (props) => {\n  const { title, description, statusCode, children } = props\n  return (\n    <>\n      <div className={useClassName(props)} role=\"alert\">\n        {statusCode === 502 ? (\n          <>Backend server down.</>\n        ) : (\n          <>\n            <h4>{title}</h4>\n            {description}\n          </>\n        )}\n      </div>\n      {children}\n    </>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/footer.tsx",
    "content": "import type { Footer } from '../models'\n\nimport { useClassName } from '../hooks/className'\n\nimport { LinkComp } from './link'\n\nexport const FooterComp = (props: Footer) => {\n  const links = props.links.map((link) => {\n    link.mode = link.mode || 'footer'\n    return link\n  })\n  const extraTextClassName = useClassName(props, { el: 'extra' })\n  return (\n    <footer className={useClassName(props)}>\n      {links.map((link, i) => (\n        <LinkComp key={i} {...link} />\n      ))}\n      {props.extraText && <div className={extraTextClassName}>{props.extraText}</div>}\n    </footer>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/form.tsx",
    "content": "import { FC, FormEvent, useContext, useState, useRef, useCallback, useEffect } from 'react'\n\nimport type { Form, ModelForm, FastProps } from '../models'\n\nimport { useClassName } from '../hooks/className'\nimport { useRequest, RequestArgs } from '../tools'\nimport { LocationContext } from '../hooks/locationContext'\nimport { usePageEventListen } from '../events'\n\nimport { AnyCompList } from './index'\n\nimport { ButtonComp } from './button'\nimport { FormFieldProps } from './FormField'\n\nexport const FormComp: FC<Form | ModelForm> = (props) => {\n  const formRef = useRef<HTMLFormElement>(null)\n  const {\n    formFields,\n    initial,\n    submitUrl,\n    method,\n    footer,\n    displayMode,\n    submitOnChange,\n    submitTrigger,\n    loading: loadingComponents,\n  } = props\n\n  // mostly equivalent to `<input disabled`\n  const [locked, setLocked] = useState(false)\n  const [fieldErrors, setFieldErrors] = useState<Record<string, string>>({})\n  const [error, setError] = useState<string | null>(null)\n  const [responseComponentProps, setResponseComponentProps] = useState<FastProps[] | null>(null)\n\n  // if form fields change or the submit url changes, clear the response\n  useEffect(() => {\n    setResponseComponentProps(null)\n  }, [formFields, submitUrl])\n\n  const request = useRequest()\n  const { goto } = useContext(LocationContext)\n\n  const submit = useCallback(\n    async (formData: FormData) => {\n      setLocked(true)\n      setError(null)\n      setFieldErrors({})\n\n      if (method === 'GOTO') {\n        // this seems to work in common cases, but typescript doesn't like it\n        const query = new URLSearchParams(formData as any)\n        for (const [k, v] of query.entries()) {\n          if (v === '') {\n            query.delete(k)\n          }\n        }\n        const queryStr = query.toString()\n        goto(queryStr === '' ? submitUrl : `${submitUrl}?${queryStr}`)\n        setLocked(false)\n        return\n      }\n\n      const requestArgs: RequestArgs = { url: submitUrl, expectedStatus: [200, 422] }\n      if (method === 'GET') {\n        // as above with URLSearchParams\n        requestArgs.query = new URLSearchParams(formData as any)\n      } else {\n        requestArgs.formData = formData\n      }\n\n      const [status, data] = await request(requestArgs)\n      if (status === 200) {\n        setResponseComponentProps(data as FastProps[])\n      } else {\n        console.assert(status === 422)\n        const errorResponse = data as ErrorResponse\n        const formErrors = errorResponse.detail.form\n        if (formErrors) {\n          setFieldErrors(Object.fromEntries(formErrors.map((e) => [locToName(e.loc), e.msg])))\n        } else {\n          console.warn('Non-field error submitting form:', data)\n          setError('Error submitting form')\n        }\n      }\n      setLocked(false)\n    },\n    [goto, method, request, submitUrl],\n  )\n\n  const onSubmit = async (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault()\n    const formData = new FormData(e.currentTarget)\n    await submit(formData)\n  }\n\n  const onChange = useCallback(() => {\n    submitOnChange && formRef.current && formRef.current.requestSubmit()\n  }, [submitOnChange])\n\n  const { fireId } = usePageEventListen(submitTrigger)\n\n  useEffect(() => {\n    fireId && formRef.current && formRef.current.requestSubmit()\n  }, [fireId])\n\n  const fieldProps: FormFieldProps[] = formFields.map((formField) => {\n    const f = {\n      ...formField,\n      error: fieldErrors[formField.name],\n      locked,\n      displayMode,\n      onChange,\n    } as FormFieldProps\n    const formInitial = initial && initial[formField.name]\n    if (formInitial !== undefined) {\n      ;(f as any).initial = formInitial\n    }\n    return f\n  })\n\n  const containerClassName = useClassName(props, { el: 'form-container' })\n  const formClassName = useClassName(props)\n\n  if (responseComponentProps) {\n    return (\n      <div className={containerClassName}>\n        <AnyCompList propsList={responseComponentProps} />\n      </div>\n    )\n  } else {\n    return (\n      <div className={containerClassName}>\n        <form ref={formRef} className={formClassName} onSubmit={onSubmit}>\n          {locked && loadingComponents && <AnyCompList propsList={loadingComponents} />}\n          <AnyCompList propsList={fieldProps} />\n          {error ? <div>Error: {error}</div> : null}\n          <Footer footer={footer} />\n        </form>\n      </div>\n    )\n  }\n}\n\nconst Footer: FC<{ footer?: FastProps[] }> = ({ footer }) => {\n  if (typeof footer === 'undefined') {\n    return <ButtonComp type=\"Button\" text=\"Submit\" htmlType=\"submit\" />\n  } else {\n    return <AnyCompList propsList={footer} />\n  }\n}\n\ntype Loc = (string | number)[]\ninterface Error {\n  type: string\n  loc: Loc\n  msg: string\n}\n\ninterface ErrorResponse {\n  detail: { form?: Error[] }\n}\n\n/**\n * Should match `loc_to_name` in python so errors can be connected to the correct field\n */\nfunction locToName(loc: Loc): string {\n  if (loc.some((v) => typeof v === 'string' && v.includes('.'))) {\n    return JSON.stringify(loc)\n  } else if (typeof loc[0] === 'string' && loc[0].startsWith('[')) {\n    return JSON.stringify(loc)\n  } else {\n    return loc.join('.')\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/heading.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Heading } from '../models'\n\nimport { useClassName } from '../hooks/className'\nimport { slugify } from '../tools'\n\nexport const HeadingComp: FC<Heading> = (props) => {\n  const { level, text, htmlId } = props\n  const HeadingComponent = getComponent(level)\n  return <HeadingComponent text={text} id={htmlId || slugify(text)} className={useClassName(props)} />\n}\n\nfunction getComponent(level: 1 | 2 | 3 | 4 | 5 | 6): FC<{ text: string; id?: string; className?: string }> {\n  switch (level) {\n    case 1:\n      return ({ text, ...rest }) => <h1 {...rest}>{text}</h1>\n    case 2:\n      return ({ text, ...rest }) => <h2 {...rest}>{text}</h2>\n    case 3:\n      return ({ text, ...rest }) => <h3 {...rest}>{text}</h3>\n    case 4:\n      return ({ text, ...rest }) => <h4 {...rest}>{text}</h4>\n    case 5:\n      return ({ text, ...rest }) => <h5 {...rest}>{text}</h5>\n    case 6:\n      return ({ text, ...rest }) => <h6 {...rest}>{text}</h6>\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/image.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Image } from '../models'\n\nimport { useClassName } from '../hooks/className'\nimport { useFireEvent } from '../events'\n\nexport const ImageComp: FC<Image> = (props) => {\n  const { src, alt, width, height, referrerPolicy, loading, onClick } = props\n\n  const { fireEvent } = useFireEvent()\n\n  return (\n    <img\n      className={useClassName(props)}\n      src={src}\n      alt={alt}\n      width={width}\n      height={height}\n      referrerPolicy={referrerPolicy}\n      loading={loading}\n      onClick={() => fireEvent(onClick)}\n    />\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/index.tsx",
    "content": "import { FC } from 'react'\n\nimport type { FastProps, Display, Text, ServerLoad, PageTitle, FireEvent } from '../models'\n\nimport { DisplayError } from '../hooks/error'\nimport { useCustomRender } from '../hooks/config'\nimport { unreachable } from '../tools'\n\nimport { TextComp } from './text'\nimport { ParagraphComp } from './paragraph'\nimport { PageTitleComp } from './PageTitle'\nimport { DivComp } from './div'\nimport { HeadingComp } from './heading'\nimport { MarkdownComp } from './Markdown'\nimport { CodeComp } from './Code'\nimport { FormComp } from './form'\nimport {\n  FormFieldInputComp,\n  FormFieldTextareaComp,\n  FormFieldBooleanComp,\n  FormFieldSelectComp,\n  FormFieldSelectSearchComp,\n  FormFieldFileComp,\n} from './FormField'\nimport { ButtonComp } from './button'\nimport { LinkComp, LinkRender } from './link'\nimport { LinkListComp } from './LinkList'\nimport { NavbarComp } from './navbar'\nimport { ModalComp } from './modal'\nimport { TableComp } from './table'\nimport { PaginationComp } from './pagination'\nimport { DetailsComp } from './details'\nimport { DisplayComp } from './display'\nimport { JsonComp } from './Json'\nimport { FooterComp } from './footer'\nimport { ServerLoadComp } from './ServerLoad'\nimport { ImageComp } from './image'\nimport { IframeComp } from './Iframe'\nimport { VideoComp } from './video'\nimport { FireEventComp } from './FireEvent'\nimport { ErrorComp } from './error'\nimport { SpinnerComp } from './spinner'\nimport { CustomComp } from './Custom'\nimport { ToastComp } from './toast'\n\n// TODO some better way to export components\nexport {\n  TextComp,\n  ParagraphComp,\n  PageTitleComp,\n  DivComp,\n  HeadingComp,\n  MarkdownComp,\n  CodeComp,\n  FormComp,\n  FormFieldInputComp,\n  FormFieldBooleanComp,\n  FormFieldSelectComp,\n  FormFieldSelectSearchComp,\n  FormFieldFileComp,\n  ButtonComp,\n  LinkComp,\n  LinkListComp,\n  NavbarComp,\n  ModalComp,\n  TableComp,\n  PaginationComp,\n  DetailsComp,\n  DisplayComp,\n  JsonComp,\n  FooterComp,\n  ServerLoadComp,\n  ImageComp,\n  IframeComp,\n  VideoComp,\n  FireEventComp,\n  ErrorComp,\n  SpinnerComp,\n  CustomComp,\n  LinkRender,\n  ToastComp,\n}\n\nexport type FastClassNameProps = Exclude<FastProps, Text | Display | ServerLoad | PageTitle | FireEvent>\n\nexport const AnyCompList: FC<{ propsList: FastProps[] }> = ({ propsList }) => (\n  <>\n    {propsList.map((child, i) => (\n      <AnyComp key={i} {...child} />\n    ))}\n  </>\n)\n\nexport const AnyComp: FC<FastProps> = (props) => {\n  const CustomRenderComp = useCustomRender(props)\n  if (CustomRenderComp) {\n    return <CustomRenderComp />\n  }\n\n  const { type } = props\n  try {\n    switch (type) {\n      case 'Text':\n        return <TextComp {...props} />\n      case 'Paragraph':\n        return <ParagraphComp {...props} />\n      case 'PageTitle':\n        return <PageTitleComp {...props} />\n      case 'Div':\n      case 'Page':\n        return <DivComp {...props} />\n      case 'Heading':\n        return <HeadingComp {...props} />\n      case 'Markdown':\n        return <MarkdownComp {...props} />\n      case 'Code':\n        return <CodeComp {...props} />\n      case 'Button':\n        return <ButtonComp {...props} />\n      case 'Link':\n        return <LinkComp {...props} />\n      case 'LinkList':\n        return <LinkListComp {...props} />\n      case 'Navbar':\n        return <NavbarComp {...props} />\n      case 'Footer':\n        return <FooterComp {...props} />\n      case 'Form':\n      case 'ModelForm':\n        return <FormComp {...props} />\n      case 'FormFieldInput':\n        return <FormFieldInputComp {...props} />\n      case 'FormFieldTextarea':\n        return <FormFieldTextareaComp {...props} />\n      case 'FormFieldBoolean':\n        return <FormFieldBooleanComp {...props} />\n      case 'FormFieldFile':\n        return <FormFieldFileComp {...props} />\n      case 'FormFieldSelect':\n        return <FormFieldSelectComp {...props} />\n      case 'FormFieldSelectSearch':\n        return <FormFieldSelectSearchComp {...props} />\n      case 'Modal':\n        return <ModalComp {...props} />\n      case 'Table':\n        return <TableComp {...props} />\n      case 'Pagination':\n        return <PaginationComp {...props} />\n      case 'Details':\n        return <DetailsComp {...props} />\n      case 'Display':\n        return <DisplayComp {...props} />\n      case 'JSON':\n        return <JsonComp {...props} />\n      case 'ServerLoad':\n        return <ServerLoadComp {...props} />\n      case 'Image':\n        return <ImageComp {...props} />\n      case 'Iframe':\n        return <IframeComp {...props} />\n      case 'Video':\n        return <VideoComp {...props} />\n      case 'FireEvent':\n        return <FireEventComp {...props} />\n      case 'Error':\n        return <ErrorComp {...props} />\n      case 'Spinner':\n        return <SpinnerComp {...props} />\n      case 'Custom':\n        return <CustomComp {...props} />\n      case 'Toast':\n        return <ToastComp {...props} />\n      default:\n        unreachable('Unexpected component type', type, props)\n        return <DisplayError title=\"Invalid Server Response\" description={`Unknown component type: \"${type}\"`} />\n    }\n  } catch (e) {\n    // TODO maybe we shouldn't catch this error (by default)?\n    const description = (e as any).message\n    return <DisplayError title=\"Render Error\" description={description} />\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/link.tsx",
    "content": "import { FC, MouseEventHandler, ReactNode, useContext } from 'react'\n\nimport type { Link, AnyEvent } from '../models'\n\nimport { useClassName } from '../hooks/className'\nimport { LocationContext } from '../hooks/locationContext'\nimport { useFireEvent } from '../events'\n\nimport { AnyCompList } from './index'\n\nexport const LinkComp: FC<Link> = (props) => (\n  <LinkRender className={useClassName(props)} onClick={props.onClick} locked={props.locked}>\n    <AnyCompList propsList={props.components} />\n  </LinkRender>\n)\n\ninterface LinkRenderProps {\n  children: ReactNode\n  locked?: boolean\n  onClick?: AnyEvent\n  className?: string\n  ariaLabel?: string\n}\n\nexport const LinkRender: FC<LinkRenderProps> = (props) => {\n  const { className, ariaLabel, children, onClick, locked } = props\n\n  const { fireEvent } = useFireEvent()\n  const { computeQuery } = useContext(LocationContext)\n\n  let href = locked ? undefined : '#'\n  if (!locked && onClick && onClick.type === 'go-to') {\n    if (onClick.url) {\n      href = onClick.url\n    } else if (onClick.query) {\n      href = computeQuery(onClick.query)\n    }\n  }\n\n  const clickHandler: MouseEventHandler<HTMLAnchorElement> = (e) => {\n    e.preventDefault()\n    if (!locked) {\n      fireEvent(onClick)\n    }\n  }\n\n  return (\n    <a href={href} className={className} onClick={clickHandler} aria-label={ariaLabel} aria-disabled={locked}>\n      {children}\n    </a>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/modal.tsx",
    "content": "import { FC, useEffect } from 'react'\n\nimport type { Modal } from '../models'\n\nimport { usePageEventListen } from '../events'\n\nexport const ModalComp: FC<Modal> = (props) => {\n  const { title, openTrigger, openContext } = props\n\n  const { fireId, clear } = usePageEventListen(openTrigger, openContext)\n\n  useEffect(() => {\n    if (fireId) {\n      setTimeout(() => {\n        alert(`${title}\\n\\nNote: modals are not implemented by pure FastUI, implement a component for 'ModalProps'.`)\n        clear()\n      })\n    }\n  }, [fireId, title, clear])\n\n  return <></>\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/navbar.tsx",
    "content": "import type { Navbar } from '../models'\n\nimport { useClassName } from '../hooks/className'\n\nimport { LinkComp, LinkRender } from './link'\n\nexport const NavbarComp = (props: Navbar) => {\n  const startLinks = props.startLinks.map((link) => {\n    link.mode = link.mode || 'navbar'\n    return link\n  })\n  const endLinks = props.endLinks.map((link) => {\n    link.mode = link.mode || 'navbar'\n    return link\n  })\n  return (\n    <nav className={useClassName(props)}>\n      <div className={useClassName(props, { el: 'contents' })}>\n        <NavbarTitle {...props} />\n        {startLinks.map((link, i) => (\n          <LinkComp key={i} {...link} />\n        ))}\n        {endLinks.map((link, i) => (\n          <LinkComp key={i} {...link} />\n        ))}\n      </div>\n    </nav>\n  )\n}\n\nconst NavbarTitle = (props: Navbar) => {\n  const { title, titleEvent } = props\n  const className = useClassName(props, { el: 'title' })\n  if (title) {\n    if (titleEvent) {\n      return (\n        <LinkRender onClick={titleEvent} className={className}>\n          {title}\n        </LinkRender>\n      )\n    } else {\n      return <span className={className}>{title}</span>\n    }\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/pagination.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Pagination, Link } from '../models'\n\nimport { useClassName } from '../hooks/className'\n\nimport { LinkListComp } from './LinkList'\n\nexport const PaginationComp: FC<Pagination> = (props) => {\n  const { page, pageCount } = props\n  const className = useClassName(props)\n\n  if (pageCount === 1) return null\n\n  const links: Link[] = [\n    {\n      type: 'Link',\n      components: [{ type: 'Text', text: 'Previous' }],\n      locked: page !== 1,\n      onClick: { type: 'go-to', query: { page: page - 1 } },\n    },\n    {\n      type: 'Link',\n      components: [{ type: 'Text', text: 'Next' }],\n      locked: page !== pageCount,\n      onClick: { type: 'go-to', query: { page: page + 1 } },\n    },\n  ]\n\n  return (\n    <div className={className}>\n      <LinkListComp type=\"LinkList\" links={links} mode=\"pagination\" />\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/paragraph.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Paragraph } from '../models'\n\nimport { useClassName } from '../hooks/className'\n\nexport const ParagraphComp: FC<Paragraph> = (props) => {\n  const { text } = props\n\n  return <p className={useClassName(props)}>{text}</p>\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/spinner.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Spinner } from '../models'\n\nimport { useClassName } from '../hooks/className'\n\nexport const SpinnerComp: FC<Spinner> = (props) => {\n  const { text } = props\n\n  return (\n    <div className={useClassName(props)}>\n      <div className={useClassName(props, { el: 'text' })}>{text}</div>\n      <div className={useClassName(props, { el: 'animation' })}>\n        <div className=\"fastui-spinner-animation\">loading...</div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/table.tsx",
    "content": "import { FC, CSSProperties } from 'react'\n\nimport type { Table } from '../models'\n\nimport { asTitle } from '../tools'\nimport { useClassName } from '../hooks/className'\n\nimport { DisplayComp, DisplayLookupProps, DataModel, renderEvent } from './display'\n\nexport const TableComp: FC<Table> = (props) => {\n  const { columns, data, noDataMessage } = props\n  const noDataClassName = useClassName(props, { el: 'no-data-message' })\n\n  return (\n    <table className={useClassName(props)}>\n      <thead>\n        <tr>\n          {columns.map((col, id) => (\n            <th key={id} style={colWidth(col.tableWidthPercent)}>\n              {col.title ?? asTitle(col.field)}\n            </th>\n          ))}\n        </tr>\n      </thead>\n      <tbody>\n        {data.map((row, rowId) => (\n          <tr key={rowId}>\n            {columns.map((column, id) => (\n              <Cell key={id} row={row} column={column} />\n            ))}\n          </tr>\n        ))}\n      </tbody>\n      {data.length === 0 && <caption className={noDataClassName}>{noDataMessage || 'No data'}</caption>}\n    </table>\n  )\n}\n\nconst colWidth = (w: number | undefined): CSSProperties | undefined => (w ? { width: `${w}%` } : undefined)\n\nconst Cell: FC<{ row: DataModel; column: DisplayLookupProps }> = ({ row, column }) => {\n  const { field, onClick, ...rest } = column\n  const value = row[field]\n  const renderedOnClick = renderEvent(onClick, row)\n  return (\n    <td>\n      <DisplayComp type=\"Display\" onClick={renderedOnClick} value={value !== undefined ? value : null} {...rest} />\n    </td>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/text.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Text } from '../models'\n\nexport const TextComp: FC<Text> = ({ text }) => <>{text}</>\n"
  },
  {
    "path": "src/npm-fastui/src/components/toast.tsx",
    "content": "import { FC, useEffect } from 'react'\n\nimport type { Toast } from '../models'\n\nimport { usePageEventListen } from '../events'\n\nexport const ToastComp: FC<Toast> = (props) => {\n  const { title, openTrigger, openContext } = props\n\n  const { fireId, clear } = usePageEventListen(openTrigger, openContext)\n\n  useEffect(() => {\n    if (fireId) {\n      setTimeout(() => {\n        alert(`${title}\\n\\nNote: modals are not implemented by pure FastUI, implement a component for 'ToastProps'.`)\n        clear()\n      })\n    }\n  }, [fireId, title, clear])\n\n  return <></>\n}\n"
  },
  {
    "path": "src/npm-fastui/src/components/video.tsx",
    "content": "import { FC } from 'react'\n\nimport type { Video } from '../models'\n\nexport const VideoComp: FC<Video> = (props) => {\n  const { sources, autoplay, controls, loop, muted, poster, width, height } = props\n  return (\n    <video\n      autoPlay={autoplay}\n      controls={controls}\n      loop={loop}\n      muted={muted}\n      poster={poster}\n      width={width}\n      height={height}\n    >\n      {sources.map((src, i) => (\n        <source key={i} src={src} />\n      ))}\n    </video>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/controller.tsx",
    "content": "import { useContext, useEffect, useState } from 'react'\n\nimport { LocationContext } from './hooks/locationContext'\nimport { ServerLoadFetch } from './components/ServerLoad'\nimport { loadEvent, LoadEventDetail } from './events'\n\nexport function FastUIController() {\n  const { fullPath } = useContext(LocationContext)\n  const [path, setPath] = useState(fullPath)\n  const [reloadValue, setReloadValue] = useState(0)\n\n  useEffect(() => {\n    function onEvent(e: Event) {\n      const { path, reloadValue } = (e as CustomEvent<LoadEventDetail>).detail\n\n      setPath(path ?? fullPath)\n      setReloadValue(reloadValue ?? 0)\n    }\n\n    document.addEventListener(loadEvent, onEvent)\n\n    return () => {\n      document.removeEventListener(loadEvent, onEvent)\n    }\n  }, [fullPath])\n\n  return <ServerLoadFetch path={path} devReload={reloadValue} />\n}\n"
  },
  {
    "path": "src/npm-fastui/src/dev.tsx",
    "content": "import { FC, useContext, useEffect } from 'react'\n\nimport { sleep } from './tools'\nimport { ErrorContext } from './hooks/error'\nimport { fireLoadEvent } from './events'\nimport { ConfigContext } from './hooks/config'\n\nlet devConnected = false\n\nexport const DevReload: FC<{ enabled?: boolean }> = ({ enabled }) => {\n  if (typeof enabled === 'undefined') {\n    enabled = process.env.NODE_ENV === 'development'\n  }\n\n  if (enabled) {\n    return <DevReloadActive />\n  } else {\n    return <></>\n  }\n}\n\nconst DevReloadActive = () => {\n  const { setError } = useContext(ErrorContext)\n  const { APIRootUrl } = useContext(ConfigContext)\n\n  useEffect(() => {\n    let listening = true\n    let lastValue = 0\n\n    async function listen() {\n      let count = 0\n      let failCount = 0\n      // this avoids connecting twice when vite is reloading\n      await sleep(100)\n      while (true) {\n        if (!listening || failCount >= 5) {\n          return count\n        }\n        const response = await fetch(APIRootUrl + '/__dev__/reload')\n        count++\n        console.debug(`dev reload connected ${count}...`)\n        // if the response is okay, and we previously failed, clear error\n        if (response.ok && failCount > 0) {\n          setError(null)\n        } else if (response.status === 404) {\n          console.log('dev reload endpoint not found, disabling dev reload')\n          return count\n        }\n        // await like this means we wait for the entire response to be received\n        const text = await response.text()\n        if (response.ok && text.startsWith('fastui-dev-reload')) {\n          failCount = 0\n          const valueMatch = text.match(/(\\d+)$/)\n          const value = valueMatch ? parseInt(valueMatch[1]!) : 0\n          if (value !== lastValue) {\n            lastValue = value\n            // wait long enough for the server to be back online\n            await sleep(300)\n            console.debug('dev reloading')\n            fireLoadEvent({ reloadValue: value })\n            setError(null)\n          }\n        } else if (response.ok) {\n          console.log(\"dev reload endpoint didn't return magic value, disabling dev reload\")\n          return count\n        } else {\n          failCount++\n          await sleep(2000)\n        }\n      }\n    }\n\n    if (!devConnected) {\n      devConnected = true\n      listen().then((count) => count > 0 && console.debug('dev reload disconnected.'))\n      return () => {\n        listening = false\n        devConnected = false\n      }\n    }\n  }, [setError, APIRootUrl])\n  return <></>\n}\n"
  },
  {
    "path": "src/npm-fastui/src/events.ts",
    "content": "import { useContext, useState, useEffect, useCallback } from 'react'\n\nimport type { PageEvent, AnyEvent } from './models'\n\nimport { LocationContext } from './hooks/locationContext'\nimport { ContextType } from './hooks/eventContext'\nimport { AUTH_TOKEN_KEY } from './tools'\n\nexport interface PageEventDetail {\n  clear: boolean\n  context?: ContextType\n}\n\nfunction pageEventType(event: PageEvent): string {\n  return `fastui:${event.name}`\n}\n\nexport function useFireEvent(): { fireEvent: (event?: AnyEvent) => void } {\n  const location = useContext(LocationContext)\n\n  function fireEventImpl(event?: AnyEvent) {\n    if (!event) {\n      return\n    }\n    console.debug('firing event', event)\n    const { type } = event\n    switch (type) {\n      case 'page': {\n        if (event.pushPath) {\n          location.gotoCosmetic(event.pushPath)\n        }\n        const detail: PageEventDetail = { clear: event.clear || false, context: event.context }\n        document.dispatchEvent(new CustomEvent(pageEventType(event), { detail }))\n        if (event.nextEvent) {\n          fireEventImpl(event.nextEvent)\n        }\n        break\n      }\n      case 'go-to':\n        if (event.url) {\n          if (event.target) {\n            window.open(event.url, event.target)\n          } else {\n            location.goto(event.url)\n          }\n        }\n        if (event.query) {\n          location.setQuery(event.query)\n        }\n        break\n      case 'auth':\n        if (event.token) {\n          localStorage.setItem(AUTH_TOKEN_KEY, event.token)\n        } else {\n          localStorage.removeItem(AUTH_TOKEN_KEY)\n        }\n        if (event.url) {\n          location.goto(event.url)\n        }\n        break\n      case 'back':\n        location.back()\n        break\n    }\n  }\n\n  // fireEventImpl is recursive, but it doesn't make sense for fireEvent to have fireEventImpl as a dep\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  const fireEvent = useCallback(fireEventImpl, [location])\n\n  return { fireEvent }\n}\n\nexport const loadEvent = 'fastui:load'\n\nexport interface LoadEventDetail {\n  path?: string\n  reloadValue?: number\n}\n\nexport function fireLoadEvent(detail: LoadEventDetail) {\n  document.dispatchEvent(new CustomEvent(loadEvent, { detail }))\n}\n\ninterface EventDetails {\n  eventContext: ContextType | null\n  fireId: string | null\n  clear: () => void\n}\n\nexport function usePageEventListen(event?: PageEvent, initialContext: ContextType | null = null): EventDetails {\n  const [eventContext, setEventContext] = useState<ContextType | null>(initialContext)\n  const [fireId, setFireId] = useState<string | null>(null)\n\n  const eventType = event && pageEventType(event)\n\n  useEffect(() => {\n    if (!eventType) {\n      setEventContext(null)\n      setFireId(null)\n      return\n    }\n\n    const onEvent = (e: Event) => {\n      const event = e as CustomEvent<PageEventDetail>\n      const { context, clear } = event.detail\n      if (clear) {\n        setEventContext(null)\n        setFireId(null)\n      } else {\n        setEventContext(context || {})\n        setFireId(`${event.type}:${event.timeStamp}`)\n      }\n    }\n\n    document.addEventListener(eventType, onEvent)\n    return () => document.removeEventListener(eventType, onEvent)\n  }, [eventType])\n\n  return {\n    eventContext,\n    fireId,\n    clear: useCallback(() => {\n      setEventContext(null)\n      setFireId(null)\n    }, []),\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/hooks/className.ts",
    "content": "import { createContext, useContext } from 'react'\n\nimport type { FastClassNameProps } from '../components'\nimport type { ClassName } from '../models'\n\nimport { LocationContext } from './locationContext'\n\ninterface ClassNameGeneratorArgs {\n  props: FastClassNameProps\n  fullPath: string\n  subElement?: string\n}\n\nexport type ClassNameGenerator = (args: ClassNameGeneratorArgs) => ClassName | undefined\nexport const ClassNameContext = createContext<ClassNameGenerator | null>(null)\n\ninterface UseClassNameExtra {\n  // default className to use if the class name generator is not set or returns undefined.\n  dft?: ClassName\n  // identifier of the element within the component to generate the class name for.\n  el?: string\n}\n\n/**\n * Generates a `className` from `props`, `classNameGenerator` or the default value.\n *\n * @param props The full props object sent from the backend, this is passed to the class name generator.\n * @param extra dft class name or sub-element\n */\nexport function useClassName(props: FastClassNameProps, extra?: UseClassNameExtra): string | undefined {\n  const classNameGenerator = useContext(ClassNameContext)\n  const { fullPath } = useContext(LocationContext)\n  let { dft, el } = extra || {}\n  const genArgs: ClassNameGeneratorArgs = { props, fullPath, subElement: el }\n\n  if (el) {\n    // if getting the class for a sub-element, we don't care about `props.ClassName`\n    if (classNameGenerator) {\n      const generated = classNameGenerator(genArgs)\n      if (generated) {\n        return renderClassName(classNameGenerator(genArgs))\n      }\n    }\n    return renderClassName(dft)\n  } else {\n    const { className } = props\n    if (combineClassNameProp(className)) {\n      if (classNameGenerator) {\n        dft = classNameGenerator(genArgs) || dft\n      }\n      return combine(dft, className)\n    } else {\n      return renderClassName(className)\n    }\n  }\n}\n\n/**\n * Decide whether we should generate combine the props class name with the generated or default, or not.\n *\n * e.g. if the ClassName contains a `+` if it's an Array or Record, or starts with `+ `\n * then we generate the default className and append the user's className to it.\n * @param classNameProp\n */\nfunction combineClassNameProp(classNameProp?: ClassName): boolean {\n  if (Array.isArray(classNameProp)) {\n    // classNameProp is an array, check if it contains `+`\n    return classNameProp.some((c) => c === '+')\n  } else if (typeof classNameProp === 'string') {\n    // classNameProp is a string, check if it starts with `+ `\n    return /^\\+ /.test(classNameProp)\n  } else if (typeof classNameProp === 'object') {\n    // classNameProp is an object, check if its keys contain `+`\n    return Object.keys(classNameProp).some((key) => key === '+')\n  } else {\n    // classNameProp is undefined, return true as we want to generate the default className\n    return true\n  }\n}\n\nfunction combine(cn1?: ClassName, cn2?: ClassName): string {\n  if (!cn1) {\n    return renderClassName(cn2)\n  } else if (!cn2) {\n    return renderClassName(cn1)\n  } else {\n    return renderClassName(cn1) + ' ' + renderClassName(cn2)\n  }\n}\n\n/**\n * Renders the className to a string, removing plus signs.\n * @param className\n */\nexport function renderClassName(className?: ClassName): string {\n  if (typeof className === 'string') {\n    return className.replace(/^\\+ /, '')\n  } else if (Array.isArray(className)) {\n    return className\n      .filter((c) => c !== '+')\n      .map(renderClassName)\n      .join(' ')\n  } else if (typeof className === 'object') {\n    return Object.entries(className)\n      .filter(([key, value]) => key !== '+' && !!value)\n      .map(([key]) => key)\n      .join(' ')\n  } else {\n    return ''\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/hooks/config.ts",
    "content": "import { createContext, FC, useContext } from 'react'\n\nimport type { FastUIProps } from '../index'\nimport type { FastProps } from '../models'\n\ntype Config = Omit<FastUIProps, 'DisplayError' | 'classNameGenerator' | 'devMode'>\n\nexport const ConfigContext = createContext<Config>({ APIRootUrl: '' })\n\nexport const useCustomRender = (props: FastProps): FC | void => {\n  const { customRender } = useContext(ConfigContext)\n\n  if (customRender) {\n    return customRender(props)\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/hooks/error.tsx",
    "content": "import { createContext, FC, ReactNode, useCallback, useContext, useState } from 'react'\n\nimport type { Error as ErrorProps } from '../models'\n\nimport { ErrorComp } from '../components'\n\nimport { useCustomRender } from './config'\n\ninterface ErrorDetails {\n  title: string\n  description: string\n  statusCode?: number\n}\n\ninterface ErrorDisplayProps extends ErrorDetails {\n  children?: ReactNode\n}\n\ninterface ErrorContextType {\n  error: ErrorDetails | null\n  setError: (error: ErrorDetails | null) => void\n}\n\nexport const DisplayError: FC<ErrorDisplayProps> = ({ title, description, statusCode, children }) => {\n  const props: ErrorProps = {\n    title,\n    description,\n    statusCode,\n    children,\n    type: 'Error',\n  }\n  const CustomRenderComp = useCustomRender(props)\n  if (CustomRenderComp) {\n    return <CustomRenderComp />\n  } else {\n    return <ErrorComp {...props} />\n  }\n}\n\nexport const ErrorContext = createContext<ErrorContextType>({\n  error: null,\n  setError: () => null,\n})\n\nconst MaybeError: FC<{ children: ReactNode }> = ({ children }) => {\n  const { error } = useContext(ErrorContext)\n  if (error) {\n    return <DisplayError {...error}>{children}</DisplayError>\n  } else {\n    return <>{children}</>\n  }\n}\n\ninterface Props {\n  children: ReactNode\n}\n\nexport const ErrorContextProvider: FC<Props> = ({ children }) => {\n  const [error, setErrorState] = useState<ErrorDetails | null>(null)\n\n  const setError = useCallback(\n    (error: ErrorDetails | null) => {\n      if (error) {\n        console.warn('setting error:', error)\n      }\n      setErrorState(error)\n    },\n    [setErrorState],\n  )\n\n  return (\n    <ErrorContext.Provider value={{ error, setError }}>\n      <MaybeError>{children}</MaybeError>\n    </ErrorContext.Provider>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/hooks/eventContext.tsx",
    "content": "import { createContext, FC, ReactNode, useCallback, useContext } from 'react'\n\nexport type ContextType = Record<string, string | number>\n\nconst EventContext = createContext<ContextType | null>(null)\n\nexport const useEventContext = (): ((template: string) => string) => {\n  const context = useContext(EventContext)\n\n  return useCallback((template: string): string => applyContext(template, context), [context])\n}\n\nexport const EventContextProvider: FC<{ children: ReactNode; context: ContextType | null }> = ({\n  children,\n  context,\n}) => {\n  return <EventContext.Provider value={context}>{children}</EventContext.Provider>\n}\n\nconst applyContext = (template: string, context: ContextType | null): string => {\n  if (!context) {\n    return template\n  }\n\n  return template.replace(/{(.+?)}/g, (_, key: string): string => {\n    const v = context[key]\n    if (v === undefined) {\n      throw new Error(`field \"${key}\" not found in ${JSON.stringify(context)}`)\n    } else {\n      return v.toString()\n    }\n  })\n}\n"
  },
  {
    "path": "src/npm-fastui/src/hooks/locationContext.tsx",
    "content": "import { createContext, ReactNode, useEffect, useState, useCallback, useContext } from 'react'\n\nimport { fireLoadEvent } from '../events'\n\nimport { ErrorContext } from './error'\n\nfunction parseLocation(): string {\n  const { href, origin } = window.location\n  // remove origin from the beginning of href\n  return href.slice(origin.length)\n}\n\nexport interface LocationState {\n  fullPath: string\n  goto: (pushPath: string) => void\n  computeQuery: (queryUpdate: Record<string, string | number | null>) => string\n  setQuery: (queryUpdate: Record<string, string | number | null>) => void\n  // like `goto`, but does not fire `fireLoadEvent`\n  gotoCosmetic: (pushPath: string) => void\n  back: () => void\n}\n\nconst initialPath = parseLocation()\n\nconst initialState = {\n  fullPath: initialPath,\n  goto: () => null,\n  computeQuery: () => '',\n  setQuery: () => null,\n  gotoCosmetic: () => null,\n  back: () => null,\n}\n\nexport const LocationContext = createContext<LocationState>(initialState)\n\nexport function LocationProvider({ children }: { children: ReactNode }) {\n  const [fullPath, setFullPath] = useState(initialPath)\n  const { setError } = useContext(ErrorContext)\n\n  const onPopState = useCallback(() => {\n    const fullPath = parseLocation()\n    setError(null)\n    setFullPath(fullPath)\n    fireLoadEvent({ path: fullPath })\n  }, [setError, setFullPath])\n\n  useEffect(() => {\n    window.addEventListener('popstate', onPopState)\n    return () => {\n      window.removeEventListener('popstate', onPopState)\n    }\n  }, [onPopState])\n\n  const pushPath = useCallback(\n    (newPath: string): string => {\n      if (newPath === '.' || newPath === '') {\n        newPath = stripQuery(fullPath)\n      } else if (!newPath.startsWith('/')) {\n        // get rid of `.` and `./` at the beginning of the path\n        if (newPath.startsWith('.')) {\n          newPath = newPath.slice(1)\n          if (newPath.startsWith('/')) {\n            newPath = newPath.slice(1)\n          }\n        }\n\n        const oldPath = stripQuery(fullPath)\n        // we're now sure newPath does not start with a `/`\n        if (oldPath.endsWith('/') || newPath.startsWith('?')) {\n          newPath = oldPath + newPath\n        } else {\n          newPath = oldPath + '/' + newPath\n        }\n      }\n\n      window.history.pushState(null, '', newPath)\n      setError(null)\n      setFullPath(newPath)\n      return newPath\n    },\n    [setError, fullPath],\n  )\n  const computeQuery = useCallback(\n    (queryUpdate: Record<string, string | number | null>): string => {\n      const query = getQuery(fullPath)\n      for (const [key, value] of Object.entries(queryUpdate)) {\n        if (value === null) {\n          query.delete(key)\n        } else {\n          query.set(key, value.toString())\n        }\n      }\n      const queryString = query.toString()\n      if (queryString !== '') {\n        return '?' + queryString\n      } else {\n        return ''\n      }\n    },\n    [fullPath],\n  )\n\n  const value: LocationState = {\n    fullPath,\n    goto: useCallback(\n      (newPath) => {\n        if (newPath.startsWith('http')) {\n          window.location.href = newPath\n        } else {\n          const path = pushPath(newPath)\n          fireLoadEvent({ path })\n        }\n      },\n      [pushPath],\n    ),\n    computeQuery,\n    setQuery: useCallback(\n      (queryUpdate) => {\n        const newPath = stripQuery(fullPath) + computeQuery(queryUpdate)\n        const path = pushPath(newPath)\n        fireLoadEvent({ path })\n      },\n      [computeQuery, fullPath, pushPath],\n    ),\n    gotoCosmetic: useCallback(\n      (newPath) => {\n        pushPath(newPath)\n      },\n      [pushPath],\n    ),\n    back: useCallback(() => {\n      window.history.back()\n    }, []),\n  }\n\n  return <LocationContext.Provider value={value}>{children}</LocationContext.Provider>\n}\n\nexport function pathMatch(matchPath: string | boolean | undefined, fullPath: string): boolean {\n  const path = stripQuery(fullPath)\n  if (typeof matchPath === 'string') {\n    if (matchPath.startsWith('regex:')) {\n      const regex = new RegExp(matchPath.slice(6))\n      return regex.test(path)\n    } else if (matchPath.startsWith('startswith:')) {\n      return path.startsWith(matchPath.slice(11))\n    } else {\n      return path === matchPath\n    }\n  } else if (matchPath === undefined) {\n    return false\n  } else {\n    return matchPath\n  }\n}\n\nfunction stripQuery(fullPath: string): string {\n  const q = fullPath.indexOf('?')\n  if (q === -1) {\n    return fullPath\n  } else {\n    return fullPath.slice(0, q)\n  }\n}\n\nfunction getQuery(fullPath: string): URLSearchParams {\n  const q = fullPath.indexOf('?')\n  if (q === -1) {\n    return new URLSearchParams()\n  } else {\n    return new URLSearchParams(fullPath.slice(q + 1))\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui/src/index.tsx",
    "content": "import { FC, ReactNode } from 'react'\n\nimport type { FastProps } from './models'\n\nimport { LocationProvider } from './hooks/locationContext'\nimport { FastUIController } from './controller'\nimport { ClassNameContext, ClassNameGenerator } from './hooks/className'\nimport { ErrorContextProvider } from './hooks/error'\nimport { ConfigContext } from './hooks/config'\nimport { DevReload } from './dev'\nexport type * as models from './models'\nexport * as components from './components'\nexport * as events from './events'\nexport type { ClassNameGenerator } from './hooks/className'\nexport { useClassName, renderClassName } from './hooks/className'\nexport { pathMatch } from './hooks/locationContext'\nexport { EventContextProvider } from './hooks/eventContext'\n\nexport type CustomRender = (props: FastProps) => FC | void\n\nexport interface FastUIProps {\n  APIRootUrl: string\n  // defaults to 'append'\n  APIPathMode?: 'append' | 'query'\n  // start of the path to remove from the URL before making a request to the API\n  APIPathStrip?: string\n  NotFound?: FC<{ url: string }>\n  Transition?: FC<{ children: ReactNode; transitioning: boolean }>\n  classNameGenerator?: ClassNameGenerator\n  customRender?: CustomRender\n  // defaults to `process.env.NODE_ENV === 'development'\n  devMode?: boolean\n}\n\nexport function FastUI(props: FastUIProps) {\n  const { classNameGenerator, devMode, ...rest } = props\n  return (\n    <ClassNameContext.Provider value={classNameGenerator ?? null}>\n      <ErrorContextProvider>\n        <LocationProvider>\n          <ConfigContext.Provider value={rest}>\n            <DevReload enabled={devMode} />\n            <FastUIController />\n          </ConfigContext.Provider>\n        </LocationProvider>\n      </ErrorContextProvider>\n    </ClassNameContext.Provider>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui/src/models.d.ts",
    "content": "/**\n * This file was automatically generated by json-schema-to-typescript.\n * DO NOT MODIFY IT BY HAND. Instead, modify python types, then run\n * `fastui generate <python-object> <typescript-output-file>`.\n */\n\nexport type FastProps =\n  | Text\n  | Paragraph\n  | PageTitle\n  | Div\n  | Page\n  | Heading\n  | Markdown\n  | Code\n  | Json\n  | Button\n  | Link\n  | LinkList\n  | Navbar\n  | Footer\n  | Modal\n  | ServerLoad\n  | Image\n  | Iframe\n  | Video\n  | FireEvent\n  | Error\n  | Spinner\n  | Custom\n  | Table\n  | Pagination\n  | Display\n  | Details\n  | Form\n  | FormFieldInput\n  | FormFieldTextarea\n  | FormFieldBoolean\n  | FormFieldFile\n  | FormFieldSelect\n  | FormFieldSelectSearch\n  | ModelForm\n  | Toast\nexport type ClassName =\n  | string\n  | ClassName[]\n  | {\n      [k: string]: boolean\n    }\nexport type JsonData =\n  | string\n  | number\n  | boolean\n  | null\n  | JsonData[]\n  | {\n      [k: string]: JsonData\n    }\nexport type AnyEvent = PageEvent | GoToEvent | BackEvent | AuthEvent\n/**\n * Display mode for a value.\n */\nexport type DisplayMode =\n  | 'auto'\n  | 'plain'\n  | 'datetime'\n  | 'date'\n  | 'duration'\n  | 'as_title'\n  | 'markdown'\n  | 'json'\n  | 'inline_code'\n  | 'currency'\n/**\n * Display mode for a value.\n */\nexport type DisplayMode1 =\n  | 'auto'\n  | 'plain'\n  | 'datetime'\n  | 'date'\n  | 'duration'\n  | 'as_title'\n  | 'markdown'\n  | 'json'\n  | 'inline_code'\n  | 'currency'\nexport type SelectOptions = SelectOption[] | SelectGroup[]\n\n/**\n * Text component that displays a string.\n */\nexport interface Text {\n  text: string\n  type: 'Text'\n}\n/**\n * Paragraph component that displays a string as a paragraph.\n */\nexport interface Paragraph {\n  text: string\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Paragraph'\n}\n/**\n * Sets the title of the HTML page via the `document.title` property.\n */\nexport interface PageTitle {\n  text: string\n  type: 'PageTitle'\n}\n/**\n * A generic container component.\n */\nexport interface Div {\n  components: FastProps[]\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Div'\n}\n/**\n * Similar to `container` in many UI frameworks, this acts as a root component for most pages.\n */\nexport interface Page {\n  components: FastProps[]\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Page'\n}\n/**\n * Heading component.\n */\nexport interface Heading {\n  text: string\n  level: 1 | 2 | 3 | 4 | 5 | 6\n  htmlId?: string\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Heading'\n}\n/**\n * Markdown component that renders markdown text.\n */\nexport interface Markdown {\n  text: string\n  codeStyle?: string\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Markdown'\n}\n/**\n * Code component that renders code with syntax highlighting.\n */\nexport interface Code {\n  text: string\n  language?: string\n  codeStyle?: string\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Code'\n}\n/**\n * JSON component that renders JSON data.\n */\nexport interface Json {\n  value: JsonData\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'JSON'\n}\n/**\n * Button component.\n */\nexport interface Button {\n  text: string\n  onClick?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  htmlType?: 'button' | 'reset' | 'submit'\n  namedStyle?: 'primary' | 'secondary' | 'warning'\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Button'\n}\nexport interface PageEvent {\n  name: string\n  pushPath?: string\n  context?: ContextType\n  clear?: boolean\n  nextEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  type: 'page'\n}\nexport interface ContextType {\n  [k: string]: string | number\n}\nexport interface GoToEvent {\n  url?: string\n  query?: {\n    [k: string]: string | number\n  }\n  target?: '_blank'\n  type: 'go-to'\n}\nexport interface BackEvent {\n  type: 'back'\n}\nexport interface AuthEvent {\n  token: string | false\n  url?: string\n  type: 'auth'\n}\n/**\n * Link component.\n */\nexport interface Link {\n  components: FastProps[]\n  onClick?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  mode?: 'navbar' | 'footer' | 'tabs' | 'vertical' | 'pagination'\n  active?: string | boolean\n  locked?: boolean\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Link'\n}\n/**\n * List of Link components.\n */\nexport interface LinkList {\n  links: Link[]\n  mode?: 'tabs' | 'vertical' | 'pagination'\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'LinkList'\n}\n/**\n * Navbar component used for moving between pages.\n */\nexport interface Navbar {\n  title?: string\n  titleEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  startLinks: Link[]\n  endLinks: Link[]\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Navbar'\n}\n/**\n * Footer component.\n */\nexport interface Footer {\n  links: Link[]\n  extraText?: string\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Footer'\n}\n/**\n * Modal component that displays a modal dialog.\n */\nexport interface Modal {\n  title: string\n  body: FastProps[]\n  footer?: FastProps[]\n  openTrigger?: PageEvent1\n  openContext?: ContextType1\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Modal'\n}\nexport interface PageEvent1 {\n  name: string\n  pushPath?: string\n  context?: ContextType\n  clear?: boolean\n  nextEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  type: 'page'\n}\nexport interface ContextType1 {\n  [k: string]: string | number\n}\n/**\n * A component that will be replaced by the server with the component returned by the given URL.\n */\nexport interface ServerLoad {\n  path: string\n  loadTrigger?: PageEvent2\n  components?: FastProps[]\n  sse?: boolean\n  sseRetry?: number\n  method?: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'\n  type: 'ServerLoad'\n}\nexport interface PageEvent2 {\n  name: string\n  pushPath?: string\n  context?: ContextType\n  clear?: boolean\n  nextEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  type: 'page'\n}\n/**\n * Image container component.\n */\nexport interface Image {\n  src: string\n  alt?: string\n  width?: string | number\n  height?: string | number\n  referrerPolicy?:\n    | 'no-referrer'\n    | 'no-referrer-when-downgrade'\n    | 'origin'\n    | 'origin-when-cross-origin'\n    | 'same-origin'\n    | 'strict-origin'\n    | 'strict-origin-when-cross-origin'\n    | 'unsafe-url'\n  loading?: 'eager' | 'lazy'\n  onClick?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Image'\n}\n/**\n * Iframe component that displays content from a URL.\n */\nexport interface Iframe {\n  src: string\n  title?: string\n  width?: string | number\n  height?: string | number\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  srcdoc?: string\n  sandbox?: string\n  type: 'Iframe'\n}\n/**\n * Video component that displays a video or multiple videos.\n */\nexport interface Video {\n  sources: string[]\n  autoplay?: boolean\n  controls?: boolean\n  loop?: boolean\n  muted?: boolean\n  poster?: string\n  width?: string | number\n  height?: string | number\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Video'\n}\n/**\n * Fire an event.\n */\nexport interface FireEvent {\n  event: AnyEvent\n  message?: string\n  type: 'FireEvent'\n}\n/**\n * Utility component used to display an error.\n */\nexport interface Error {\n  title: string\n  description: string\n  statusCode?: number\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Error'\n  children?: ReactNode\n}\n/**\n * Spinner component that displays a loading spinner.\n */\nexport interface Spinner {\n  text?: string\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Spinner'\n}\n/**\n * Custom component that allows for special data to be rendered.\n */\nexport interface Custom {\n  data: JsonData\n  subType: string\n  library?: string\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Custom'\n}\n/**\n * Table component.\n */\nexport interface Table {\n  data: DataModel[]\n  columns: DisplayLookup[]\n  noDataMessage?: string\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Table'\n}\nexport interface DataModel {\n  [k: string]: JsonData\n}\n/**\n * Description of how to display a value looked up from data, either in a table or detail view.\n */\nexport interface DisplayLookup {\n  mode?: DisplayMode\n  title?: string\n  onClick?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  field: string\n  tableWidthPercent?: number\n}\n/**\n * Pagination component to use with tables.\n */\nexport interface Pagination {\n  page: number\n  pageSize: number\n  total: number\n  pageQueryParam?: string\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Pagination'\n  pageCount: number\n}\n/**\n * Description of how to display a value, either in a table or detail view.\n */\nexport interface Display {\n  mode?: DisplayMode1\n  title?: string\n  onClick?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  value: JsonData\n  type: 'Display'\n}\n/**\n * Details associated with displaying a data model.\n */\nexport interface Details {\n  data: DataModel\n  fields: (DisplayLookup | Display)[]\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Details'\n}\n/**\n * Form component.\n */\nexport interface Form {\n  submitUrl: string\n  initial?: {\n    [k: string]: JsonData\n  }\n  method?: 'POST' | 'GOTO' | 'GET'\n  displayMode?: 'default' | 'page' | 'inline'\n  submitOnChange?: boolean\n  submitTrigger?: PageEvent3\n  loading?: FastProps[]\n  footer?: FastProps[]\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  formFields: (\n    | FormFieldInput\n    | FormFieldTextarea\n    | FormFieldBoolean\n    | FormFieldFile\n    | FormFieldSelect\n    | FormFieldSelectSearch\n  )[]\n  type: 'Form'\n}\nexport interface PageEvent3 {\n  name: string\n  pushPath?: string\n  context?: ContextType\n  clear?: boolean\n  nextEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  type: 'page'\n}\n/**\n * Form field for basic input.\n */\nexport interface FormFieldInput {\n  name: string\n  title: string[] | string\n  required?: boolean\n  error?: string\n  locked?: boolean\n  description?: string\n  displayMode?: 'default' | 'inline'\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  htmlType?: 'text' | 'date' | 'datetime-local' | 'time' | 'email' | 'url' | 'number' | 'password' | 'hidden'\n  initial?: string | number\n  placeholder?: string\n  autocomplete?: string\n  type: 'FormFieldInput'\n}\n/**\n * Form field for text area input.\n */\nexport interface FormFieldTextarea {\n  name: string\n  title: string[] | string\n  required?: boolean\n  error?: string\n  locked?: boolean\n  description?: string\n  displayMode?: 'default' | 'inline'\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  rows?: number\n  cols?: number\n  initial?: string\n  placeholder?: string\n  autocomplete?: string\n  type: 'FormFieldTextarea'\n}\n/**\n * Form field for boolean input.\n */\nexport interface FormFieldBoolean {\n  name: string\n  title: string[] | string\n  required?: boolean\n  error?: string\n  locked?: boolean\n  description?: string\n  displayMode?: 'default' | 'inline'\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  initial?: boolean\n  mode?: 'checkbox' | 'switch'\n  type: 'FormFieldBoolean'\n}\n/**\n * Form field for file input.\n */\nexport interface FormFieldFile {\n  name: string\n  title: string[] | string\n  required?: boolean\n  error?: string\n  locked?: boolean\n  description?: string\n  displayMode?: 'default' | 'inline'\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  multiple?: boolean\n  accept?: string\n  type: 'FormFieldFile'\n}\n/**\n * Form field for select input.\n */\nexport interface FormFieldSelect {\n  name: string\n  title: string[] | string\n  required?: boolean\n  error?: string\n  locked?: boolean\n  description?: string\n  displayMode?: 'default' | 'inline'\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  options: SelectOptions\n  multiple?: boolean\n  initial?: string[] | string\n  vanilla?: boolean\n  placeholder?: string\n  autocomplete?: string\n  type: 'FormFieldSelect'\n}\nexport interface SelectOption {\n  value: string\n  label: string\n}\nexport interface SelectGroup {\n  label: string\n  options: SelectOption[]\n}\n/**\n * Form field for searchable select input.\n */\nexport interface FormFieldSelectSearch {\n  name: string\n  title: string[] | string\n  required?: boolean\n  error?: string\n  locked?: boolean\n  description?: string\n  displayMode?: 'default' | 'inline'\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  searchUrl: string\n  multiple?: boolean\n  initial?: SelectOption1\n  debounce?: number\n  placeholder?: string\n  type: 'FormFieldSelectSearch'\n}\nexport interface SelectOption1 {\n  value: string\n  label: string\n}\n/**\n * Form component generated from a Pydantic model.\n */\nexport interface ModelForm {\n  submitUrl: string\n  initial?: {\n    [k: string]: JsonData\n  }\n  method?: 'POST' | 'GOTO' | 'GET'\n  displayMode?: 'default' | 'page' | 'inline'\n  submitOnChange?: boolean\n  submitTrigger?: PageEvent4\n  loading?: FastProps[]\n  footer?: FastProps[]\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'ModelForm'\n  formFields: (\n    | FormFieldInput\n    | FormFieldTextarea\n    | FormFieldBoolean\n    | FormFieldFile\n    | FormFieldSelect\n    | FormFieldSelectSearch\n  )[]\n}\nexport interface PageEvent4 {\n  name: string\n  pushPath?: string\n  context?: ContextType\n  clear?: boolean\n  nextEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  type: 'page'\n}\n/**\n * Toast component that displays a toast message (small temporary message).\n */\nexport interface Toast {\n  title: string\n  body: FastProps[]\n  position?:\n    | 'top-start'\n    | 'top-center'\n    | 'top-end'\n    | 'middle-start'\n    | 'middle-center'\n    | 'middle-end'\n    | 'bottom-start'\n    | 'bottom-center'\n    | 'bottom-end'\n  openTrigger?: PageEvent5\n  openContext?: ContextType2\n  className?:\n    | string\n    | ClassName[]\n    | {\n        [k: string]: boolean\n      }\n  type: 'Toast'\n}\nexport interface PageEvent5 {\n  name: string\n  pushPath?: string\n  context?: ContextType\n  clear?: boolean\n  nextEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent\n  type: 'page'\n}\nexport interface ContextType2 {\n  [k: string]: string | number\n}\n"
  },
  {
    "path": "src/npm-fastui/src/tools.ts",
    "content": "import { useCallback, useContext, useEffect } from 'react'\nimport { fetchEventSource, EventStreamContentType } from '@microsoft/fetch-event-source'\n\nimport { ErrorContext } from './hooks/error'\n\nexport const AUTH_TOKEN_KEY = 'fastui-auth-token'\nexport type Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'\n\nexport function useRequest(): (args: RequestArgs) => Promise<[number, any]> {\n  const { setError } = useContext(ErrorContext)\n\n  return useCallback(\n    async (args: RequestArgs) => {\n      try {\n        return await request(args)\n      } catch (e) {\n        const title = 'Request Error'\n        if (e instanceof RequestError) {\n          setError({ title, description: e.message, statusCode: e.status })\n        } else {\n          setError({ title, description: (e as any)?.message })\n        }\n        throw e\n      }\n    },\n    [setError],\n  )\n}\n\nexport interface RequestArgs {\n  url: string\n  method?: Method\n  // defaults to 200\n  expectedStatus?: number[]\n  query?: Record<string, string> | URLSearchParams\n  json?: Record<string, any>\n  formData?: FormData\n  headers?: Record<string, string> | Headers\n}\n\nasync function request({\n  url,\n  method,\n  headers,\n  query,\n  json,\n  expectedStatus,\n  formData,\n}: RequestArgs): Promise<[number, any]> {\n  const init: RequestInit = {}\n\n  let contentType = null\n  if (json) {\n    init.body = JSON.stringify(json)\n    contentType = 'application/json'\n    method = method ?? 'POST'\n  } else if (formData) {\n    // don't set content-type, let the browser set it\n    init.body = formData\n    method = method ?? 'POST'\n  }\n\n  if (query) {\n    const searchParams = new URLSearchParams(query)\n    url = `${url}?${searchParams.toString()}`\n  }\n\n  init.headers = new Headers(headers)\n  if (contentType && !init.headers.get('Content-Type')) {\n    init.headers.set('Content-Type', contentType)\n  }\n\n  const authHeader = getAuthHeader()\n  if (authHeader) {\n    init.headers.set(authHeader.key, authHeader.value)\n  }\n\n  if (method) {\n    init.method = method\n  }\n\n  let response\n  try {\n    response = await fetch(url, init)\n  } catch (e) {\n    throw new RequestError('fetch failed', 0)\n  }\n\n  const status = await checkResponse(url, response, expectedStatus)\n  let data\n  try {\n    data = await response.json()\n  } catch (e) {\n    console.warn(`${url} -> ${status} response not valid JSON`)\n    throw new RequestError('Response not valid JSON', status)\n  }\n  console.debug(`${url} -> ${status} JSON:`, data)\n  return [status, data]\n}\n\nexport function useSSE(url: string, onMessage: (data: any) => void, method?: Method, retry?: number): void {\n  const { setError } = useContext(ErrorContext)\n\n  useEffect(() => {\n    let stop = false\n    const headers: Record<string, string> = {}\n    const authHeader = getAuthHeader()\n    if (authHeader) {\n      headers[authHeader.key] = authHeader.value\n    }\n    fetchEventSource(url, {\n      method,\n      headers,\n      onopen: async function (response) {\n        const status = await checkResponse(url, response, [200])\n        const ct = response.headers.get('content-type')\n        if (!ct || !ct.startsWith(EventStreamContentType)) {\n          console.warn(`${url} -> ${status} content-type \"${ct}\" != \"${EventStreamContentType}\"`)\n          throw new RequestError('Response not valid event stream', status)\n        }\n        console.debug(`${url} -> ${status} event stream`)\n        // ok\n      },\n      onmessage(e) {\n        if (stop) {\n          throw new SSEStopError()\n        }\n        const data = JSON.parse(e.data)\n        onMessage(data)\n      },\n      onclose() {\n        if (typeof retry === 'number') {\n          throw new SSERetryError()\n        } else {\n          throw new SSEStopError()\n        }\n      },\n      onerror(e) {\n        if (e instanceof SSERetryError) {\n          console.debug('SSE retrying')\n          return retry\n        } else {\n          throw e\n        }\n      },\n    }).catch((e) => {\n      if (e instanceof SSEStopError) {\n        // do nothing, this is fine\n        return\n      }\n      const title = 'Request Error'\n      if (e instanceof RequestError) {\n        setError({ title, description: e.message, statusCode: e.status })\n      } else {\n        setError({ title, description: (e as any)?.message })\n      }\n      throw e\n    })\n\n    return () => {\n      stop = true\n    }\n  }, [setError, url, onMessage, method, retry])\n}\n\nclass SSERetryError extends Error {}\nclass SSEStopError extends Error {}\n\nclass RequestError extends Error {\n  status: number\n\n  constructor(message: string, status: number) {\n    super(message)\n    this.status = status\n    this.name = 'RequestError'\n  }\n}\n\nfunction responseOk(response: Response, expectedStatus?: number[]) {\n  if (expectedStatus) {\n    return expectedStatus.includes(response.status)\n  } else {\n    return response.ok\n  }\n}\n\nexport function unreachable(msg: string, unexpectedValue: never, args?: any) {\n  console.warn(msg, { unexpectedValue }, args)\n}\n\ntype Callable = (...args: any[]) => void\n\nexport function debounce<C extends Callable>(fn: C, delay: number): C {\n  let timerId: any\n\n  // @ts-expect-error - functions are contravariant, so this should be fine, no idea how to satisfy TS though\n  return (...args: any[]) => {\n    clearTimeout(timerId)\n    timerId = setTimeout(() => fn(...args), delay)\n  }\n}\n\nexport async function sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n// usage `as_title('what_ever') > 'What Ever'`\nexport const asTitle = (s: string): string => s.replace(/[_-]/g, ' ').replace(/(_|\\b)\\w/g, (l) => l.toUpperCase())\n\nexport const slugify = (s: string): string =>\n  s\n    .toLowerCase()\n    .replace(/\\s+/g, '-') // Replace spaces with -\n    .replace(/[^\\w-]+/g, '') // Remove all non-word characters\n    .replace(/--+/g, '-') // Replace multiple - with single -\n    .replace(/^-+/, '') // Trim - from start of text\n    .replace(/-+$/, '') // Trim - from end of text\n\nfunction getAuthHeader(): { key: string; value: string } | undefined {\n  const authToken = localStorage.getItem(AUTH_TOKEN_KEY)\n  if (authToken) {\n    // we use a custom auth-schema as well-known values like `Basic` and `Bearer` are not correct here\n    return { key: 'Authorization', value: `Token ${authToken}` }\n  }\n}\n\nasync function checkResponse(url: string, response: Response, expectedStatus: number[] | undefined): Promise<number> {\n  const { status } = response\n  if (!responseOk(response, expectedStatus)) {\n    let detail: null | string = null\n    const content = await response.text()\n    try {\n      const jsonData = JSON.parse(content)\n      console.warn(`${url} -> ${status} JSON:`, jsonData)\n      if (typeof jsonData.detail === 'string') {\n        detail = jsonData.detail\n      }\n    } catch (e) {\n      console.warn(`${url} -> ${status} content:`, content)\n      detail = content\n    }\n    const msg = `${detail || response.statusText} (${status})`\n    throw new RequestError(msg, status)\n  }\n  return status\n}\n"
  },
  {
    "path": "src/npm-fastui/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"dist\"\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "src/npm-fastui/typedoc.json",
    "content": "// TODO: we really want the entryPoint to be src, but mkdocstrings-typescript doesn't fully support this option yet,\n// as we can't specify the path within the package from which we want to pull docs, so right now\n// we resort to more specific entryPoints\n{\n  \"extends\": [\"../../typedoc.base.json\"],\n  \"entryPointStrategy\": \"expand\",\n  \"entryPoints\": [\"src/models.d.ts\"]\n}\n"
  },
  {
    "path": "src/npm-fastui-bootstrap/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2023 to present Pydantic Services inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "src/npm-fastui-bootstrap/README.md",
    "content": "# FastUI Bootstrap\n\nBootstrap components for [FastUI](https://github.com/pydantic/FastUI).\n"
  },
  {
    "path": "src/npm-fastui-bootstrap/package.json",
    "content": "{\n  \"name\": \"@pydantic/fastui-bootstrap\",\n  \"version\": \"0.0.26\",\n  \"description\": \"Bootstrap renderer for FastUI\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"author\": \"Samuel Colvin\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://github.com/pydantic/fastui\",\n  \"private\": false,\n  \"keywords\": [\n    \"fastui\",\n    \"bootstrap\",\n    \"jsx\",\n    \"typescript\",\n    \"react\",\n    \"fastapi\"\n  ],\n  \"scripts\": {\n    \"prepublishOnly\": \"rm -rf dist && tsc\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"typewatch\": \"tsc --noEmit --watch\"\n  },\n  \"dependencies\": {\n    \"bootstrap\": \"^5.3.2\",\n    \"react\": \"^18.2.0\",\n    \"react-bootstrap\": \"^2.9.1\",\n    \"react-dom\": \"^18.2.0\",\n    \"sass\": \"^1.69.5\"\n  },\n  \"peerDependencies\": {\n    \"@pydantic/fastui\": \"0.0.26\"\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui-bootstrap/src/footer.tsx",
    "content": "import { FC } from 'react'\nimport { components, models, useClassName } from 'fastui'\n\nexport const Footer: FC<models.Footer> = (props) => {\n  const links = props.links.map((link) => {\n    link.mode = link.mode || 'footer'\n    return link\n  })\n  const extraProp = useClassName(props, { el: 'extra' })\n  return (\n    <footer className={useClassName(props)}>\n      <ul className={useClassName(props, { el: 'link-list' })}>\n        {links.map((link, i) => (\n          <li key={i} className=\"nav-item\">\n            <components.LinkComp {...link} />\n          </li>\n        ))}\n      </ul>\n      {props.extraText && <div className={extraProp}>{props.extraText}</div>}\n    </footer>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui-bootstrap/src/index.tsx",
    "content": "import { pathMatch } from 'fastui'\n\nimport type { ClassNameGenerator, CustomRender, models } from 'fastui'\n\nimport { Modal } from './modal'\nimport { Navbar } from './navbar'\nimport { Pagination } from './pagination'\nimport { Footer } from './footer'\nimport { Toast } from './toast'\n\nexport const customRender: CustomRender = (props) => {\n  const { type } = props\n  switch (type) {\n    case 'Navbar':\n      return () => <Navbar {...props} />\n    case 'Footer':\n      return () => <Footer {...props} />\n    case 'Modal':\n      return () => <Modal {...props} />\n    case 'Pagination':\n      return () => <Pagination {...props} />\n    case 'Toast':\n      return () => <Toast {...props} />\n  }\n}\n\nexport const classNameGenerator: ClassNameGenerator = ({\n  props,\n  fullPath,\n  subElement,\n}): models.ClassName | undefined => {\n  const { type } = props\n  switch (type) {\n    case 'Page':\n      return 'container mt-80 mb-3 page'\n    case 'Button':\n      return {\n        btn: true,\n        'btn-primary': !props.namedStyle || props.namedStyle === 'primary',\n        'btn-secondary': props.namedStyle === 'secondary',\n        'btn-warning': props.namedStyle === 'warning',\n      }\n    case 'Table':\n      switch (subElement) {\n        case 'no-data-message':\n          return 'text-center mt-2'\n        default:\n          return 'table table-striped table-bordered'\n      }\n    case 'Details':\n      switch (subElement) {\n        case 'dt':\n          return 'col-sm-3 col-md-2 text-sm-end'\n        case 'dd':\n          return 'col-sm-9 col-md-10'\n        default:\n          return 'row'\n      }\n    case 'Form':\n    case 'ModelForm':\n      if (props.displayMode === 'inline') {\n        switch (subElement) {\n          case 'form-container':\n            return ''\n          default:\n            return 'row row-cols-lg-4 align-items-center justify-content-end'\n        }\n      } else if (props.displayMode === 'page') {\n        switch (subElement) {\n          case 'form-container':\n            return 'row justify-content-center'\n          default:\n            return 'col-md-4'\n        }\n      } else {\n        break\n      }\n    case 'FormFieldInput':\n    case 'FormFieldTextarea':\n    case 'FormFieldBoolean':\n    case 'FormFieldSelect':\n    case 'FormFieldSelectSearch':\n    case 'FormFieldFile':\n      switch (subElement) {\n        case 'textarea':\n        case 'input':\n          return {\n            'form-control': type !== 'FormFieldBoolean',\n            'is-invalid': props.error != null,\n            'form-check-input': type === 'FormFieldBoolean',\n          }\n        case 'select':\n          return 'form-select'\n        case 'select-react':\n          return ''\n        case 'label':\n          if (props.displayMode === 'inline') {\n            return 'visually-hidden'\n          } else {\n            return { 'form-label': true, 'fw-bold': !!props.required, 'form-check-label': type === 'FormFieldBoolean' }\n          }\n        case 'error':\n          return 'invalid-feedback'\n        case 'description':\n          return 'form-text'\n        default:\n          return {\n            'mb-3': true,\n            'form-check': type === 'FormFieldBoolean',\n            'form-switch': type === 'FormFieldBoolean' && props.mode === 'switch',\n          }\n      }\n    case 'Navbar':\n      switch (subElement) {\n        case 'contents':\n          return 'container'\n        case 'title':\n          return 'navbar-brand'\n        default:\n          return 'border-bottom fixed-top bg-body'\n      }\n    case 'Footer':\n      switch (subElement) {\n        case 'link-list':\n          return 'nav justify-content-center pb-1'\n        case 'extra':\n          return 'text-center text-muted pb-3'\n        default:\n          return 'border-top pt-1 mt-auto bg-body'\n      }\n    case 'Link':\n      return {\n        active: pathMatch(props.active, fullPath),\n        'nav-link': props.mode === 'navbar' || props.mode === 'tabs' || props.mode === 'footer',\n        'text-muted': props.mode === 'footer',\n      }\n    case 'LinkList':\n      if (subElement === 'link-list-item' && props.mode) {\n        return 'nav-item'\n      } else {\n        switch (props.mode) {\n          case 'tabs':\n            return 'nav nav-underline'\n          case 'vertical':\n            return 'nav flex-column'\n          default:\n            return ''\n        }\n      }\n    case 'Code':\n      return 'rounded'\n    case 'Error':\n      if (props.statusCode === 502) {\n        return 'm-3 text-muted'\n      } else {\n        return 'error-alert alert alert-danger m-3'\n      }\n    case 'Spinner':\n      if (subElement === 'text') {\n        return 'd-flex justify-content-center mb-2'\n      } else if (subElement === 'animation') {\n        return 'd-flex justify-content-center'\n      } else {\n        return 'my-4'\n      }\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui-bootstrap/src/modal.tsx",
    "content": "import { FC } from 'react'\nimport { models, components, events, renderClassName, EventContextProvider } from 'fastui'\nimport BootstrapModal from 'react-bootstrap/Modal'\n\nexport const Modal: FC<models.Modal> = (props) => {\n  const { className, title, body, footer, openTrigger, openContext } = props\n\n  const { eventContext, fireId, clear } = events.usePageEventListen(openTrigger, openContext)\n\n  return (\n    <EventContextProvider context={eventContext}>\n      <BootstrapModal className={renderClassName(className)} show={!!fireId} onHide={clear}>\n        <BootstrapModal.Header closeButton>\n          <BootstrapModal.Title>{title}</BootstrapModal.Title>\n        </BootstrapModal.Header>\n        <BootstrapModal.Body>\n          <components.AnyCompList propsList={body} />\n        </BootstrapModal.Body>\n        {footer && (\n          <BootstrapModal.Footer className=\"modal-footer\">\n            <components.AnyCompList propsList={footer} />\n          </BootstrapModal.Footer>\n        )}\n      </BootstrapModal>\n    </EventContextProvider>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui-bootstrap/src/navbar.tsx",
    "content": "import { FC } from 'react'\nimport { components, useClassName, models } from 'fastui'\nimport BootstrapNavbar from 'react-bootstrap/Navbar'\n\nexport const Navbar: FC<models.Navbar> = (props) => {\n  const startLinks = props.startLinks.map((link) => {\n    link.mode = link.mode || 'navbar'\n    return link\n  })\n  const endLinks = props.endLinks.map((link) => {\n    link.mode = link.mode || 'navbar'\n    return link\n  })\n  return (\n    <BootstrapNavbar expand=\"lg\" className={useClassName(props)}>\n      <div className={useClassName(props, { el: 'contents' })}>\n        <NavbarTitle {...props} />\n        <BootstrapNavbar.Toggle aria-controls=\"navbar-collapse\" />\n        <BootstrapNavbar.Collapse id=\"navbar-collapse\">\n          <ul className=\"navbar-nav me-auto\">\n            {startLinks.map((link, i) => (\n              <li key={i} className=\"nav-item\">\n                <components.LinkComp {...link} />\n              </li>\n            ))}\n          </ul>\n          <ul className=\"navbar-nav ms-auto\">\n            {endLinks.map((link, i) => (\n              <li key={i} className=\"nav-item\">\n                <components.LinkComp {...link} />\n              </li>\n            ))}\n          </ul>\n        </BootstrapNavbar.Collapse>\n      </div>\n    </BootstrapNavbar>\n  )\n}\n\nconst NavbarTitle = (props: models.Navbar) => {\n  const { title, titleEvent } = props\n  const className = useClassName(props, { el: 'title' })\n  if (title) {\n    if (titleEvent) {\n      return (\n        <components.LinkRender onClick={titleEvent} className={className}>\n          {title}\n        </components.LinkRender>\n      )\n    } else {\n      return <span className={className}>{title}</span>\n    }\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui-bootstrap/src/pagination.tsx",
    "content": "import { FC } from 'react'\nimport { components, models, renderClassName } from 'fastui'\n\ninterface Link {\n  Display: FC\n  ariaLabel?: string\n  locked?: boolean\n  active?: boolean\n  page?: number\n  pageQueryParam?: string\n}\n\nexport const Pagination: FC<models.Pagination> = (props) => {\n  const { page, pageCount, pageQueryParam } = props\n  if (pageCount === 1) return null\n\n  const links: Link[] = [\n    {\n      Display: () => <span aria-hidden=\"true\">&laquo;</span>,\n      ariaLabel: 'Previous',\n      locked: page === 1,\n      page: page - 1,\n      pageQueryParam,\n    },\n    {\n      Display: () => <>1</>,\n      locked: page === 1,\n      active: page === 1,\n      page: 1,\n      pageQueryParam,\n    },\n  ]\n\n  if (page > 4) {\n    links.push({ Display: () => <>...</>, pageQueryParam })\n  }\n\n  for (let p = page - 2; p <= page + 2; p++) {\n    if (p <= 1 || p >= pageCount) continue\n    links.push({\n      Display: () => <>{p}</>,\n      locked: page === p,\n      active: page === p,\n      page: p,\n      pageQueryParam,\n    })\n  }\n\n  if (page < pageCount - 3) {\n    links.push({ Display: () => <>...</>, pageQueryParam })\n  }\n\n  links.push({\n    Display: () => <>{pageCount}</>,\n    locked: page === pageCount,\n    page: pageCount,\n    pageQueryParam,\n  })\n\n  links.push({\n    Display: () => <span aria-hidden=\"true\">&raquo;</span>,\n    ariaLabel: 'Next',\n    locked: page === pageCount,\n    page: page + 1,\n    pageQueryParam,\n  })\n\n  return (\n    <nav aria-label=\"Pagination\">\n      <ul className=\"pagination justify-content-center\">\n        {links.map((link, i) => (\n          <PaginationLink key={i} {...link} />\n        ))}\n      </ul>\n    </nav>\n  )\n}\n\nconst PaginationLink: FC<Link> = ({ Display, ariaLabel, locked, active, page, pageQueryParam }) => {\n  if (!page) {\n    return (\n      <li className=\"page-item\">\n        <span className=\"page-link px-2 text-muted\">\n          <Display />\n        </span>\n      </li>\n    )\n  }\n  const className = renderClassName({ 'page-link': true, disabled: locked && !active, active } as models.ClassName)\n  const onClick: models.GoToEvent = {\n    type: 'go-to',\n    query: { [pageQueryParam !== undefined ? pageQueryParam : 'page']: page },\n  }\n  return (\n    <li className=\"page-item\">\n      <components.LinkRender onClick={onClick} className={className} locked={locked || active} ariaLabel={ariaLabel}>\n        <Display />\n      </components.LinkRender>\n    </li>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui-bootstrap/src/toast.tsx",
    "content": "import { FC } from 'react'\nimport { components, events, renderClassName, EventContextProvider, models } from 'fastui'\nimport BootstrapToast from 'react-bootstrap/Toast'\nimport BootstrapToastContainer from 'react-bootstrap/ToastContainer'\n\nexport const Toast: FC<models.Toast> = (props) => {\n  const { className, title, body, position, openTrigger, openContext } = props\n\n  const { eventContext, fireId, clear } = events.usePageEventListen(openTrigger, openContext)\n\n  return (\n    <EventContextProvider context={eventContext}>\n      <BootstrapToastContainer position={position} className=\"position-fixed bottom-0 end-0 p-3\">\n        <BootstrapToast className={renderClassName(className)} show={!!fireId} onClose={clear}>\n          <BootstrapToast.Header>\n            <strong className=\"me-auto\">{title}</strong>\n          </BootstrapToast.Header>\n          <BootstrapToast.Body>\n            <components.AnyCompList propsList={body} />\n          </BootstrapToast.Body>\n        </BootstrapToast>\n      </BootstrapToastContainer>\n    </EventContextProvider>\n  )\n}\n"
  },
  {
    "path": "src/npm-fastui-bootstrap/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"dist\",\n    \"paths\": {\n      \"fastui\": [\"../npm-fastui/src\"]\n    }\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "src/npm-fastui-bootstrap/typedoc.json",
    "content": "{\n  \"extends\": [\"../../typedoc.base.json\"],\n  \"entryPointStrategy\": \"expand\",\n  \"entryPoints\": [\"src\"]\n}\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2023 to present Pydantic Services inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/README.md",
    "content": "# FastUI pre-build\n\nPre-built files for [FastUI](https://github.com/pydantic/FastUI).\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title></title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/package.json",
    "content": "{\n  \"name\": \"@pydantic/fastui-prebuilt\",\n  \"version\": \"0.0.26\",\n  \"description\": \"Pre-built files for FastUI\",\n  \"main\": \"dist/index.html\",\n  \"type\": \"module\",\n  \"author\": \"Samuel Colvin\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://github.com/pydantic/fastui\",\n  \"private\": false,\n  \"keywords\": [\n    \"fastui\",\n    \"jsx\",\n    \"typescript\",\n    \"react\",\n    \"fastapi\"\n  ],\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"prepublishOnly\": \"rm -rf dist && tsc --noEmit && vite build\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"typewatch\": \"tsc --noEmit --watch\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-react-swc\": \"^3.3.2\",\n    \"vite\": \"^5.0.12\"\n  }\n}\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/src/App.tsx",
    "content": "import { CustomRender, FastUI, renderClassName } from 'fastui'\nimport * as bootstrap from 'fastui-bootstrap'\nimport { FC, ReactNode } from 'react'\n\nexport default function App() {\n  return (\n    <FastUI\n      APIRootUrl={getMetaContent('fastui:APIRootUrl') || '/api'}\n      APIPathMode={getMetaContent('fastui:APIPathMode') as undefined | 'append' | 'query'}\n      APIPathStrip={getMetaContent('fastui:APIPathStrip')}\n      classNameGenerator={bootstrap.classNameGenerator}\n      customRender={customRender}\n      NotFound={NotFound}\n      Transition={Transition}\n    />\n  )\n}\n\nfunction getMetaContent(name: string): string | undefined {\n  return document.querySelector(`meta[name=\"${name}\"]`)?.getAttribute('content') || undefined\n}\n\nconst NotFound = ({ url }: { url: string }) => (\n  <div className=\"container mt-5 text-center\">\n    <h1>Page not found</h1>\n    <p>\n      No page found at <code>{url}</code>.\n    </p>\n  </div>\n)\n\nconst Transition: FC<{ children: ReactNode; transitioning: boolean }> = ({ children, transitioning }) => (\n  <>\n    <div className={renderClassName({ 'transition-overlay': true, transitioning })} />\n    {children}\n  </>\n)\n\nconst customRender: CustomRender = (props) => {\n  const { type } = props\n  if (type === 'Custom' && props.library === undefined && props.subType === 'cowsay') {\n    console.assert(typeof props.data === 'string', 'cowsay data must be a string')\n    const text = props.data as string\n    return () => <Cowsay text={text} />\n  } else {\n    return bootstrap.customRender(props)\n  }\n}\n\nconst COWSAY = ` {above}\n< {text} >\n {below}\n        \\\\   ^__^\n         \\\\  (oo)\\\\_______\n            (__)\\\\       )\\\\/\\\\\n                ||----w |\n                ||     ||`\n\nconst Cowsay: FC<{ text: string }> = ({ text }) => {\n  const len = text.length\n  const cowsay = COWSAY.replace('{text}', text)\n    .replace('{above}', '_'.repeat(len + 2))\n    .replace('{below}', '-'.repeat(len + 2))\n  return <pre>{cowsay}</pre>\n}\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/src/main.scss",
    "content": "$primary: black;\n$secondary: white;\n$link-color: #0d6efd; // bootstrap primary\n\n@import 'bootstrap/scss/bootstrap';\n\nhtml,\nbody,\n#root {\n  height: 100%;\n}\n\n#root {\n  display: flex;\n  flex-direction: column;\n}\n\n.page {\n  // margin-top because the top is sticky\n  margin-top: 70px;\n}\n\n:root {\n  --bs-font-sans-serif: 'IBM Plex Sans', sans-serif;\n  --bs-code-color: rgb(31, 35, 40);\n  //\n}\n@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,400;0,500;1,400&display=swap');\n\nbody {\n  margin-bottom: 60px;\n}\n\n.bg-body {\n  --bs-bg-opacity: 0.6;\n  backdrop-filter: blur(8px);\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  scroll-margin-top: 60px;\n}\n\n.transition-overlay {\n  position: fixed;\n  top: 0;\n  left: 0;\n  width: 0;\n  height: 0;\n  pointer-events: none;\n  background-color: white;\n  z-index: 9999;\n  opacity: 0;\n  transition: opacity 0.4s ease-in-out;\n  &.transitioning {\n    opacity: 0.8;\n    pointer-events: auto;\n    width: 100%;\n    height: 100%;\n  }\n}\n\n.fastui-markdown code {\n  padding: 0.2em 0.4em;\n  margin: 0;\n  font-size: 85%;\n  white-space: break-spaces;\n  background-color: rgba(175, 184, 193, 0.2);\n  border-radius: 6px;\n}\n\n// custom spinner from https://cssloaders.github.io/\n.fastui-spinner-animation,\n.fastui-spinner-animation:before,\n.fastui-spinner-animation:after {\n  border-radius: 50%;\n  width: 2.5em;\n  height: 2.5em;\n  animation-fill-mode: both;\n  animation: spinner-dots 1.8s infinite ease-in-out;\n}\n.fastui-spinner-animation {\n  top: -2.5em;\n  color: var(--bs-dark);\n  font-size: 7px;\n  position: relative;\n  text-indent: -9999em;\n  transform: translateZ(0);\n  animation-delay: -0.16s;\n  &:before,\n  &:after {\n    content: '';\n    position: absolute;\n    top: 0;\n  }\n  &:before {\n    left: -3.5em;\n    animation-delay: -0.32s;\n  }\n  &:after {\n    left: 3.5em;\n  }\n}\n@keyframes spinner-dots {\n  0%,\n  80%,\n  100% {\n    box-shadow: 0 2.5em 0 -1.3em;\n  }\n  40% {\n    box-shadow: 0 2.5em 0 0;\n  }\n}\n\n// make sure alerts aren't hidden behind the navbar\n.error-alert {\n  position: relative;\n  top: 60px;\n}\n\n.btn-secondary {\n  --bs-btn-border-color: #dee2e6;\n}\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/src/main.tsx",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\n\nimport App from './App'\nimport './main.scss'\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n  <React.StrictMode>\n    <App />\n  </React.StrictMode>,\n)\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/src/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"paths\": {\n      \"fastui\": [\"../npm-fastui/src\"],\n      \"fastui-bootstrap\": [\"../npm-fastui-bootstrap/src\"]\n    }\n  },\n  \"include\": [\"src\"],\n  \"references\": [{ \"path\": \"./tsconfig.node.json\" }]\n}\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/tsconfig.node.json",
    "content": "{\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"skipLibCheck\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"allowSyntheticDefaultImports\": true\n  },\n  \"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/typedoc.json",
    "content": "{\n  \"extends\": [\"../../typedoc.base.json\"],\n  \"entryPointStrategy\": \"expand\",\n  \"entryPoints\": [\"src\"]\n}\n"
  },
  {
    "path": "src/npm-fastui-prebuilt/vite.config.ts",
    "content": "import path from 'path'\n\nimport react from '@vitejs/plugin-react-swc'\nimport { defineConfig, HttpProxy } from 'vite'\n\nexport default () => {\n  const serverConfig = {\n    host: true,\n    port: 3000,\n    proxy: {\n      '/api': {\n        target: 'http://localhost:8000',\n        configure: (proxy: HttpProxy.Server) => {\n          proxy.on('error', (err, _, res) => {\n            const { code } = err as any\n            if (code === 'ECONNREFUSED') {\n              res.writeHead(502, { 'content-type': 'text/plain' })\n              res.end('vite-proxy: Proxy connection refused')\n            }\n          })\n        },\n      },\n    },\n  }\n\n  return defineConfig({\n    // @ts-expect-error - no need to type check this file\n    plugins: [react()],\n    resolve: {\n      alias: {\n        '@': path.resolve(__dirname, './src'),\n        fastui: path.resolve(__dirname, '../npm-fastui/src'),\n        'fastui-bootstrap': path.resolve(__dirname, '../npm-fastui-bootstrap/src'),\n      },\n    },\n    server: serverConfig,\n    preview: serverConfig,\n    build: {\n      sourcemap: true,\n      // we don't need hashes in URLs, we the URL will change when we release a new version\n      rollupOptions: {\n        output: {\n          entryFileNames: `assets/[name].js`,\n          chunkFileNames: `assets/[name].js`,\n          assetFileNames: `assets/[name].[ext]`,\n        },\n      },\n    },\n  })\n}\n"
  },
  {
    "path": "src/python-fastui/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2023 to present Pydantic Services inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "src/python-fastui/README.md",
    "content": "# FastUI\n\n[![CI](https://github.com/pydantic/FastUI/actions/workflows/ci.yml/badge.svg)](https://github.com/pydantic/FastUI/actions?query=event%3Apush+branch%3Amain+workflow%3ACI)\n[![versions](https://img.shields.io/pypi/pyversions/fastui.svg)](https://github.com/pydantic/FastUI)\n[![license](https://img.shields.io/github/license/pydantic/FastUI.svg)](https://github.com/pydantic/FastUI/blob/main/LICENSE)\n\nPython components for [FastUI](https://github.com/pydantic/FastUI).\n"
  },
  {
    "path": "src/python-fastui/fastui/__init__.py",
    "content": "import typing as _t\n\nimport pydantic\n\nfrom .components import AnyComponent\n\n__version__ = '0.9.0'\n__all__ = 'AnyComponent', 'FastUI', 'prebuilt_html'\n\n\nclass FastUI(pydantic.RootModel):\n    \"\"\"\n    The root component of a FastUI application.\n    \"\"\"\n\n    root: list[AnyComponent]\n\n    @pydantic.field_validator('root', mode='before')\n    def coerce_to_list(cls, v):\n        if isinstance(v, list):\n            return v\n        else:\n            return [v]\n\n\n_PREBUILT_VERSION = '0.0.26'\n_PREBUILT_CDN_URL = f'https://cdn.jsdelivr.net/npm/@pydantic/fastui-prebuilt@{_PREBUILT_VERSION}/dist/assets'\n\n\ndef prebuilt_html(\n    *,\n    title: str = '',\n    api_root_url: str | None = None,\n    api_path_mode: _t.Literal['append', 'query'] | None = None,\n    api_path_strip: str | None = None,\n) -> str:\n    \"\"\"\n    Returns a simple HTML page which includes the FastUI react frontend, loaded from https://www.jsdelivr.com/.\n\n    Arguments:\n        title: page title\n        api_root_url: the root URL of the API backend, which will be used to get data, default is '/api'.\n        api_path_mode: whether to append the page path to the root API request URL, or use it as a query parameter,\n            default is 'append'.\n        api_path_strip: string to remove from the start of the page path before making the API request.\n\n    Returns:\n        HTML string which can be returned by an endpoint to serve the FastUI frontend.\n    \"\"\"\n    meta_extra = []\n    if api_root_url is not None:\n        meta_extra.append(f'<meta name=\"fastui:APIRootUrl\" content=\"{api_root_url}\" />')\n    if api_path_mode is not None:\n        meta_extra.append(f'<meta name=\"fastui:APIPathMode\" content=\"{api_path_mode}\" />')\n    if api_path_strip is not None:\n        meta_extra.append(f'<meta name=\"fastui:APIPathStrip\" content=\"{api_path_strip}\" />')\n    meta_extra_str = '\\n    '.join(meta_extra)\n    # language=HTML\n    return f\"\"\"\\\n<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>{title}</title>\n    <script type=\"module\" crossorigin src=\"{_PREBUILT_CDN_URL}/index.js\"></script>\n    <link rel=\"stylesheet\" crossorigin href=\"{_PREBUILT_CDN_URL}/index.css\">\n    {meta_extra_str}\n  </head>\n  <body>\n    <div id=\"root\"></div>\n  </body>\n</html>\n\"\"\"\n"
  },
  {
    "path": "src/python-fastui/fastui/__main__.py",
    "content": "import argparse\nfrom pathlib import Path\n\nfrom . import __version__, generate_typescript\n\n\ndef cli():\n    parser = argparse.ArgumentParser(prog='FastUI', description='FastUI CLI.')\n    parser.add_argument(\n        '--version',\n        action='version',\n        version=f'fastui {__version__}',\n    )\n\n    subparsers = parser.add_subparsers(dest='command', required=True)\n\n    generate_typescript_parser = subparsers.add_parser(\n        'generate', help='Generate typescript types from Python definitions of FastUI components.'\n    )\n    generate_typescript_parser.add_argument(\n        'python_object', metavar='python-object', type=str, help='Python object to generate types for.'\n    )\n    generate_typescript_parser.add_argument(\n        'typescript_output_file', metavar='typescript-output-file', type=Path, help='Path to output typescript file.'\n    )\n\n    args = parser.parse_args()\n    generate_typescript.main(args.python_object, args.typescript_output_file)\n\n\nif __name__ == '__main__':\n    cli()\n"
  },
  {
    "path": "src/python-fastui/fastui/auth/__init__.py",
    "content": "from .github import GitHubAuthProvider, GitHubEmail, GitHubExchange, GithubUser\nfrom .shared import AuthError, AuthRedirect, fastapi_auth_exception_handling\n\n__all__ = (\n    'GitHubAuthProvider',\n    'GitHubExchange',\n    'GithubUser',\n    'GitHubEmail',\n    'AuthError',\n    'AuthRedirect',\n    'fastapi_auth_exception_handling',\n)\n"
  },
  {
    "path": "src/python-fastui/fastui/auth/github.py",
    "content": "from collections.abc import AsyncIterator\nfrom contextlib import asynccontextmanager\nfrom dataclasses import dataclass\nfrom datetime import datetime, timedelta, timezone\nfrom typing import TYPE_CHECKING, cast\nfrom urllib.parse import urlencode\n\nfrom pydantic import BaseModel, SecretStr, TypeAdapter, field_validator\n\nfrom .shared import AuthError\n\nif TYPE_CHECKING:\n    import httpx\n\n\n__all__ = 'GitHubAuthProvider', 'GitHubExchange', 'GithubUser', 'GitHubEmail'\n\n\n@dataclass\nclass GitHubExchangeError:\n    error: str\n    error_description: str | None = None\n\n\n@dataclass\nclass GitHubExchange:\n    access_token: str\n    token_type: str\n    scope: list[str]\n\n    @field_validator('scope', mode='before')\n    def check_scope(cls, v: str) -> list[str]:\n        return [s for s in v.split(',') if s]\n\n\ngithub_exchange_type = TypeAdapter(GitHubExchange | GitHubExchangeError)\n\n\nclass GithubUser(BaseModel):\n    login: str\n    name: str | None\n    email: str | None\n    avatar_url: str\n    created_at: datetime\n    updated_at: datetime\n    public_repos: int\n    public_gists: int\n    followers: int\n    following: int\n    company: str | None\n    blog: str | None\n    location: str | None\n    hireable: bool | None\n    bio: str | None\n    twitter_username: str | None = None\n\n\nclass GitHubEmail(BaseModel):\n    email: str\n    primary: bool\n    verified: bool\n    visibility: str | None\n\n\ngithub_emails_ta = TypeAdapter(list[GitHubEmail])\n\n\nclass GitHubAuthProvider:\n    \"\"\"\n    For details see https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps.\n    \"\"\"\n\n    def __init__(\n        self,\n        httpx_client: 'httpx.AsyncClient',\n        github_client_id: str,\n        github_client_secret: SecretStr,\n        *,\n        redirect_uri: str | None = None,\n        scopes: list[str] | None = None,\n        state_provider: 'StateProvider | bool' = True,\n        exchange_cache_age: timedelta | None = timedelta(seconds=30),\n    ):\n        \"\"\"\n        Arguments:\n            httpx_client: An instance of `httpx.AsyncClient` to use for making requests to GitHub.\n            github_client_id: The client ID of the GitHub OAuth app.\n            github_client_secret: The client secret of the GitHub OAuth app.\n            redirect_uri: The URL in your app where users will be sent after authorization, if custom\n            scopes: See https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes\n            state_provider: If `True`, use a `StateProvider` to generate and validate state parameters for the OAuth\n                flow, you can also provide an instance directly.\n            exchange_cache_age: If not `None`,\n                responses from the access token exchange are cached for the given duration.\n        \"\"\"\n        self._httpx_client = httpx_client\n        self._github_client_id = github_client_id\n        self._github_client_secret = github_client_secret\n        self._redirect_uri = redirect_uri\n        self._scopes = scopes\n        if state_provider is True:\n            self._state_provider = StateProvider(github_client_secret)\n        elif state_provider is False:\n            self._state_provider = None\n        else:\n            self._state_provider = state_provider\n        # cache exchange responses, see `exchange_code` for details\n        self._exchange_cache_age = exchange_cache_age\n\n    @classmethod\n    @asynccontextmanager\n    async def create(\n        cls,\n        client_id: str,\n        client_secret: SecretStr,\n        *,\n        redirect_uri: str | None = None,\n        state_provider: 'StateProvider | bool' = True,\n        exchange_cache_age: timedelta | None = timedelta(seconds=10),\n    ) -> AsyncIterator['GitHubAuthProvider']:\n        \"\"\"\n        Async context manager to create a GitHubAuth instance with a new `httpx.AsyncClient`.\n        \"\"\"\n        import httpx\n\n        async with httpx.AsyncClient() as client:\n            yield cls(\n                client,\n                client_id,\n                client_secret,\n                redirect_uri=redirect_uri,\n                state_provider=state_provider,\n                exchange_cache_age=exchange_cache_age,\n            )\n\n    async def authorization_url(self) -> str:\n        \"\"\"\n        See https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#1-request-a-users-github-identity\n        \"\"\"\n        params = {'client_id': self._github_client_id}\n        if self._redirect_uri:\n            params['redirect_uri'] = self._redirect_uri\n        if self._scopes:\n            params['scope'] = ' '.join(self._scopes)\n        if self._state_provider:\n            params['state'] = await self._state_provider.new_state()\n        return f'https://github.com/login/oauth/authorize?{urlencode(params)}'\n\n    async def exchange_code(self, code: str, state: str | None = None) -> GitHubExchange:\n        \"\"\"\n        Exchange a code for an access token.\n\n        If `self._exchange_cache_age` is not `None` (the default), responses are cached for the given duration to\n        work around issues with React often sending the same request multiple times in development mode.\n        \"\"\"\n        if self._exchange_cache_age:\n            cache_key = f'{code}:{state}'\n            if exchange := EXCHANGE_CACHE.get(cache_key, self._exchange_cache_age):\n                return exchange\n            else:\n                exchange = await self._exchange_code(code, state)\n                EXCHANGE_CACHE.set(cache_key, exchange)\n                return exchange\n        else:\n            return await self._exchange_code(code, state)\n\n    async def _exchange_code(self, code: str, state: str | None = None) -> GitHubExchange:\n        if self._state_provider:\n            if state is None:\n                raise AuthError('Missing GitHub auth state', code='missing_state')\n            elif not await self._state_provider.check_state(state):\n                raise AuthError('Invalid GitHub auth state', code='invalid_state')\n\n        params = {\n            'client_id': self._github_client_id,\n            'client_secret': self._github_client_secret.get_secret_value(),\n            'code': code,\n        }\n        if self._redirect_uri:\n            params['redirect_uri'] = self._redirect_uri\n\n        r = await self._httpx_client.post(\n            'https://github.com/login/oauth/access_token',\n            params=params,\n            headers={'Accept': 'application/json'},\n        )\n        r.raise_for_status()\n        exchange_response = github_exchange_type.validate_json(r.content)\n        if isinstance(exchange_response, GitHubExchangeError):\n            if exchange_response.error == 'bad_verification_code':\n                raise AuthError('Invalid GitHub verification code', code=exchange_response.error)\n            else:\n                raise RuntimeError(f'Unexpected response from GitHub access token exchange: {r.text}')\n        else:\n            return cast(GitHubExchange, exchange_response)\n\n    async def get_github_user(self, exchange: GitHubExchange) -> GithubUser:\n        \"\"\"\n        See https://docs.github.com/en/rest/users/users#get-the-authenticated-user\n        \"\"\"\n        headers = self._auth_headers(exchange)\n        user_response = await self._httpx_client.get('https://api.github.com/user', headers=headers)\n        user_response.raise_for_status()\n        return GithubUser.model_validate_json(user_response.content)\n\n    async def get_github_user_emails(self, exchange: GitHubExchange) -> list[GitHubEmail]:\n        \"\"\"\n        See https://docs.github.com/en/rest/users/emails\n        \"\"\"\n        headers = self._auth_headers(exchange)\n        emails_response = await self._httpx_client.get('https://api.github.com/user/emails', headers=headers)\n        emails_response.raise_for_status()\n        return github_emails_ta.validate_json(emails_response.content)\n\n    @staticmethod\n    def _auth_headers(exchange: GitHubExchange) -> dict[str, str]:\n        return {\n            'Authorization': f'Bearer {exchange.access_token}',\n            'Accept': 'application/vnd.github+json',\n        }\n\n\nclass ExchangeCache:\n    def __init__(self):\n        self._data: dict[str, tuple[datetime, GitHubExchange]] = {}\n\n    def get(self, key: str, max_age: timedelta) -> GitHubExchange | None:\n        self._purge(max_age)\n        if v := self._data.get(key):\n            return v[1]\n\n    def set(self, key: str, value: GitHubExchange) -> None:\n        self._data[key] = (datetime.now(), value)\n\n    def _purge(self, max_age: timedelta) -> None:\n        \"\"\"\n        Remove old items from the exchange cache\n        \"\"\"\n        min_timestamp = datetime.now() - max_age\n        to_remove = [k for k, (ts, _) in self._data.items() if ts < min_timestamp]\n        for k in to_remove:\n            del self._data[k]\n\n    def __len__(self) -> int:\n        return len(self._data)\n\n    def clear(self) -> None:\n        self._data.clear()\n\n\n# exchange cache is a singleton so instantiating a new GitHubAuthProvider reuse the same cache\nEXCHANGE_CACHE = ExchangeCache()\n\n\nclass StateProvider:\n    \"\"\"\n    This is a simple state provider for the GitHub OAuth flow which uses a JWT to create an unguessable \"state\" string.\n\n    Requires `PyJWT` to be installed.\n    \"\"\"\n\n    def __init__(self, secret: SecretStr, max_age: timedelta = timedelta(minutes=5)):\n        self._secret = secret\n        self._max_age = max_age\n\n    async def new_state(self) -> str:\n        import jwt\n\n        data = {'exp': datetime.now(tz=timezone.utc) + self._max_age}\n        return jwt.encode(data, self._secret.get_secret_value(), algorithm='HS256')\n\n    async def check_state(self, state: str) -> bool:\n        import jwt\n\n        try:\n            jwt.decode(state, self._secret.get_secret_value(), algorithms=['HS256'])\n        except (jwt.DecodeError, jwt.ExpiredSignatureError):\n            return False\n        else:\n            return True\n"
  },
  {
    "path": "src/python-fastui/fastui/auth/shared.py",
    "content": "import json\nfrom abc import ABC, abstractmethod\nfrom typing import TYPE_CHECKING\n\nfrom .. import AnyComponent, FastUI, events\nfrom .. import components as c\n\nif TYPE_CHECKING:\n    from fastapi import FastAPI\n\n__all__ = 'AuthError', 'AuthRedirect', 'fastapi_auth_exception_handling'\n\n\nclass AuthException(ABC, Exception):\n    \"\"\"\n    Base exception for all auth-related errors.\n    \"\"\"\n\n    @abstractmethod\n    def response_data(self) -> tuple[int, str]:\n        raise NotImplementedError\n\n\nclass AuthError(AuthException):\n    def __init__(self, message: str, *, code: str):\n        super().__init__(message)\n        self.code = code\n\n    def response_data(self) -> tuple[int, str]:\n        return 401, json.dumps({'detail': str(self)})\n\n\nclass AuthRedirect(AuthException):\n    \"\"\"\n    Special exception which should cause a 345 HTTP response with a body containing\n    FastUI components to redirect the user to a new page.\n    \"\"\"\n\n    def __init__(self, path: str, message: str | None = None):\n        super().__init__(f'Auth redirect to `{path}`' + (f': {message}' if message else ''))\n        self.path = path\n        self.message = message\n\n    def response_data(self) -> tuple[int, str]:\n        components: list[AnyComponent] = [c.FireEvent(event=events.GoToEvent(url=self.path), message=self.message)]\n        return 345, FastUI(root=components).model_dump_json(exclude_none=True)\n\n\ndef fastapi_auth_exception_handling(app: 'FastAPI') -> None:\n    \"\"\"\n    Register an exception handler for any `AuthException` in a FastAPI app.\n    \"\"\"\n    from fastapi import Request, Response\n\n    @app.exception_handler(AuthException)\n    def auth_exception_handler(_request: Request, e: AuthException) -> Response:\n        status_code, body = e.response_data()\n        return Response(body, media_type='application/json', status_code=status_code)\n"
  },
  {
    "path": "src/python-fastui/fastui/base.py",
    "content": "from pydantic import AliasGenerator, ConfigDict\nfrom pydantic import BaseModel as _BaseModel\nfrom pydantic.alias_generators import to_camel\n\n\nclass BaseModel(_BaseModel):\n    model_config = ConfigDict(alias_generator=AliasGenerator(serialization_alias=to_camel))\n"
  },
  {
    "path": "src/python-fastui/fastui/class_name.py",
    "content": "# could be renamed to something general if there's more to add\nfrom typing import Annotated, Literal\n\nfrom pydantic import Field\nfrom typing_extensions import TypeAliasType\n\nClassName = TypeAliasType('ClassName', str | list['ClassName'] | dict[str, bool | None] | None)\nClassNameField = Annotated[ClassName, Field(serialization_alias='className')]\n\nNamedStyle = TypeAliasType('NamedStyle', Literal['primary', 'secondary', 'warning'] | None)\nNamedStyleField = Annotated[NamedStyle, Field(serialization_alias='namedStyle')]\n"
  },
  {
    "path": "src/python-fastui/fastui/components/__init__.py",
    "content": "\"\"\"\nComponent definitions.\n\nAll CamelCase names in the namespace should be components.\n\"\"\"\nimport typing as _t\n\nimport pydantic as _p\nimport typing_extensions as _te\nfrom pydantic_core import core_schema as _core_schema\n\nfrom .. import class_name as _class_name\nfrom .. import events\nfrom .. import types as _types\nfrom ..base import BaseModel\nfrom .display import Details, Display\nfrom .forms import (\n    BaseForm,\n    Form,\n    FormField,\n    FormFieldBoolean,\n    FormFieldFile,\n    FormFieldInput,\n    FormFieldSelect,\n    FormFieldSelectSearch,\n    ModelForm,\n)\nfrom .tables import Pagination, Table\n\n__all__ = (\n    # first we include all components from this file\n    'Text',\n    'Paragraph',\n    'PageTitle',\n    'Div',\n    'Page',\n    'Heading',\n    'Markdown',\n    'Code',\n    'Json',\n    'Button',\n    'Link',\n    'LinkList',\n    'Navbar',\n    'Modal',\n    'ServerLoad',\n    'Image',\n    'Iframe',\n    'FireEvent',\n    'Error',\n    'Spinner',\n    'Toast',\n    'Custom',\n    # then we include components from other files\n    'Table',\n    'Pagination',\n    'Display',\n    'Details',\n    'Form',\n    'FormField',\n    'ModelForm',\n    'Footer',\n    # then `AnyComponent` itself\n    'AnyComponent',\n    # then the other form field types which are included in `AnyComponent` via the `FormField` union\n    'FormFieldBoolean',\n    'FormFieldFile',\n    'FormFieldInput',\n    'FormFieldSelect',\n    'FormFieldSelectSearch',\n)\n\n\nclass Text(BaseModel, extra='forbid'):\n    \"\"\"Text component that displays a string.\"\"\"\n\n    text: str\n    \"\"\"The text to display.\"\"\"\n\n    type: _t.Literal['Text'] = 'Text'\n    \"\"\"The type of the component. Always 'Text'.\"\"\"\n\n\nclass Paragraph(BaseModel, extra='forbid'):\n    \"\"\"Paragraph component that displays a string as a paragraph.\"\"\"\n\n    text: str\n    \"\"\"The text to display.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the paragraph's HTML component.\"\"\"\n\n    type: _t.Literal['Paragraph'] = 'Paragraph'\n    \"\"\"The type of the component. Always 'Paragraph'.\"\"\"\n\n\nclass PageTitle(BaseModel, extra='forbid'):\n    \"\"\"Sets the title of the HTML page via the `document.title` property.\"\"\"\n\n    text: str\n    \"\"\"The text to set as the page title.\"\"\"\n\n    type: _t.Literal['PageTitle'] = 'PageTitle'\n    \"\"\"The type of the component. Always 'PageTitle'.\"\"\"\n\n\nclass Div(BaseModel, defer_build=True, extra='forbid'):\n    \"\"\"A generic container component.\"\"\"\n\n    components: 'list[AnyComponent]'\n    \"\"\"List of components to render inside the div.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the div's HTML component.\"\"\"\n\n    type: _t.Literal['Div'] = 'Div'\n    \"\"\"The type of the component. Always 'Div'.\"\"\"\n\n\nclass Page(BaseModel, defer_build=True, extra='forbid'):\n    \"\"\"Similar to `container` in many UI frameworks, this acts as a root component for most pages.\"\"\"\n\n    components: 'list[AnyComponent]'\n    \"\"\"List of components to render on the page.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the page's HTML component.\"\"\"\n\n    type: _t.Literal['Page'] = 'Page'\n    \"\"\"The type of the component. Always 'Page'.\"\"\"\n\n\nclass Heading(BaseModel, extra='forbid'):\n    \"\"\"Heading component.\"\"\"\n\n    text: str\n    \"\"\"The text to display in the heading.\"\"\"\n\n    level: _t.Literal[1, 2, 3, 4, 5, 6] = 1\n    \"\"\"The level of the heading. 1 is the largest, 6 is the smallest.\"\"\"\n\n    html_id: str | None = None\n    \"\"\"Optional HTML ID to apply to the heading's HTML component.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the page's HTML component.\"\"\"\n\n    type: _t.Literal['Heading'] = 'Heading'\n    \"\"\"The type of the component. Always 'Heading'.\"\"\"\n\n    @classmethod\n    def __get_pydantic_json_schema__(\n        cls, core_schema: _core_schema.CoreSchema, handler: _p.GetJsonSchemaHandler\n    ) -> _t.Any:\n        # until https://github.com/pydantic/pydantic/issues/8413 is fixed\n        json_schema = handler(core_schema)\n        schema_def = handler.resolve_ref_schema(json_schema)\n        schema_def['required'].append('level')\n        return json_schema\n\n\nCodeStyle = _te.Annotated[str | None, _p.Field(serialization_alias='codeStyle')]\n\"\"\"\nCode style to apply to a `Code` component.\n\nAttributes:\n    codeStyle: The code style to apply. If None, no style is applied.\n\nSee Also:\n    - [PrismJS Themes](https://github.com/PrismJS/prism-themes)\n    - [PrismJS Theme Index](https://cdn.jsdelivr.net/npm/react-syntax-highlighter@15.5.0/dist/esm/styles/prism/index.js)\n\"\"\"\n\n\nclass Markdown(BaseModel, extra='forbid'):\n    \"\"\"Markdown component that renders markdown text.\"\"\"\n\n    text: str\n    \"\"\"The markdown text to render.\"\"\"\n\n    code_style: CodeStyle = None\n    \"\"\"Optional code style to apply to the markdown text.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the page's HTML component.\"\"\"\n\n    type: _t.Literal['Markdown'] = 'Markdown'\n    \"\"\"The type of the component. Always 'Markdown'.\"\"\"\n\n\nclass Code(BaseModel, extra='forbid'):\n    \"\"\"Code component that renders code with syntax highlighting.\"\"\"\n\n    text: str\n    \"\"\"The code to render.\"\"\"\n\n    language: str | None = None\n    \"\"\"Optional language of the code. If None, no syntax highlighting is applied.\"\"\"\n\n    code_style: CodeStyle = None\n    \"\"\"Optional code style to apply to the code.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the page's HTML component.\"\"\"\n\n    type: _t.Literal['Code'] = 'Code'\n    \"\"\"The type of the component. Always 'Code'.\"\"\"\n\n\nclass Json(BaseModel, extra='forbid'):\n    \"\"\"JSON component that renders JSON data.\"\"\"\n\n    value: _types.JsonData\n    \"\"\"The JSON data to render.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the page's HTML component.\"\"\"\n\n    type: _t.Literal['JSON'] = 'JSON'\n    \"\"\"The type of the component. Always 'JSON'.\"\"\"\n\n\nclass Button(BaseModel, extra='forbid'):\n    \"\"\"Button component.\"\"\"\n\n    text: str\n    \"\"\"The text to display on the button.\"\"\"\n\n    on_click: events.AnyEvent | None = None\n    \"\"\"Optional event to trigger when the button is clicked.\"\"\"\n\n    html_type: _t.Literal['button', 'reset', 'submit'] | None = None\n    \"\"\"Optional HTML type of the button. If None, defaults to 'button'.\"\"\"\n\n    named_style: _class_name.NamedStyleField = None\n    \"\"\"Optional named style to apply to the button.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the button's HTML component.\"\"\"\n\n    type: _t.Literal['Button'] = 'Button'\n    \"\"\"The type of the component. Always 'Button'.\"\"\"\n\n\nclass Link(BaseModel, defer_build=True, extra='forbid'):\n    \"\"\"Link component.\"\"\"\n\n    components: 'list[AnyComponent]'\n    \"\"\"List of components to render attached to the link.\"\"\"\n\n    on_click: events.AnyEvent | None = None\n    \"\"\"Optional event to trigger when the link is clicked.\"\"\"\n\n    mode: _t.Literal['navbar', 'footer', 'tabs', 'vertical', 'pagination'] | None = None\n    \"\"\"Optional mode of the link.\"\"\"\n\n    active: str | bool | None = None\n    \"\"\"Optional active state of the link.\"\"\"\n\n    locked: bool | None = None\n    \"\"\"Optional locked state of the link.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the link's HTML component.\"\"\"\n\n    type: _t.Literal['Link'] = 'Link'\n    \"\"\"The type of the component. Always 'Link'.\"\"\"\n\n\nclass LinkList(BaseModel, extra='forbid'):\n    \"\"\"List of Link components.\"\"\"\n\n    links: list[Link]\n    \"\"\"List of links to render.\"\"\"\n\n    mode: _t.Literal['tabs', 'vertical', 'pagination'] | None = None\n    \"\"\"Optional mode of the link list.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the link list's HTML component.\"\"\"\n\n    type: _t.Literal['LinkList'] = 'LinkList'\n    \"\"\"The type of the component. Always 'LinkList'.\"\"\"\n\n\nclass Navbar(BaseModel, extra='forbid'):\n    \"\"\"Navbar component used for moving between pages.\"\"\"\n\n    title: str | None = None\n    \"\"\"Optional title to display in the navbar.\"\"\"\n\n    title_event: events.AnyEvent | None = None\n    \"\"\"Optional event to trigger when the title is clicked. Often used to navigate to the home page.\"\"\"\n\n    start_links: list[Link] = []\n    \"\"\"List of links to render at the start of the navbar.\"\"\"\n\n    end_links: list[Link] = []\n    \"\"\"List of links to render at the end of the navbar.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the navbar's HTML component.\"\"\"\n\n    type: _t.Literal['Navbar'] = 'Navbar'\n    \"\"\"The type of the component. Always 'Navbar'.\"\"\"\n\n    @classmethod\n    def __get_pydantic_json_schema__(\n        cls, core_schema: _core_schema.CoreSchema, handler: _p.GetJsonSchemaHandler\n    ) -> _t.Any:\n        # until https://github.com/pydantic/pydantic/issues/8413 is fixed\n        json_schema = handler(core_schema)\n        schema_def = handler.resolve_ref_schema(json_schema)\n        schema_def.setdefault('required', []).extend(['startLinks', 'endLinks'])\n        return json_schema\n\n\nclass Footer(BaseModel, extra='forbid'):\n    \"\"\"Footer component.\"\"\"\n\n    links: list[Link]\n    \"\"\"List of links to render in the footer.\"\"\"\n\n    extra_text: str | None = None\n    \"\"\"Optional extra text to display in the footer.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the footer's HTML component.\"\"\"\n\n    type: _t.Literal['Footer'] = 'Footer'\n    \"\"\"The type of the component. Always 'Footer'.\"\"\"\n\n\nclass Modal(BaseModel, defer_build=True, extra='forbid'):\n    \"\"\"Modal component that displays a modal dialog.\"\"\"\n\n    title: str\n    \"\"\"The text displayed on the modal trigger button.\"\"\"\n\n    body: 'list[AnyComponent]'\n    \"\"\"List of components to render in the modal body.\"\"\"\n\n    footer: 'list[AnyComponent] | None' = None\n    \"\"\"Optional list of components to render in the modal footer.\"\"\"\n\n    open_trigger: events.PageEvent | None = None\n    \"\"\"Optional event to trigger when the modal is opened.\"\"\"\n\n    open_context: events.ContextType | None = None\n    \"\"\"Optional context to pass to the open trigger event.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the modal's HTML component.\"\"\"\n\n    type: _t.Literal['Modal'] = 'Modal'\n    \"\"\"The type of the component. Always 'Modal'.\"\"\"\n\n\nclass ServerLoad(BaseModel, defer_build=True, extra='forbid'):\n    \"\"\"A component that will be replaced by the server with the component returned by the given URL.\"\"\"\n\n    path: str\n    \"\"\"The URL to load the component from.\"\"\"\n\n    load_trigger: events.PageEvent | None = None\n    \"\"\"Optional event to trigger when the component is loaded.\"\"\"\n\n    components: 'list[AnyComponent] | None' = None\n    \"\"\"Optional list of components to render while the server is loading the new component(s).\"\"\"\n\n    sse: bool | None = None\n    \"\"\"Optional flag to enable server-sent events (SSE) for the server load.\"\"\"\n\n    sse_retry: int | None = None\n    \"\"\"Optional time in milliseconds to retry the SSE connection.\"\"\"\n\n    method: _t.Literal['GET', 'POST', 'PATCH', 'PUT', 'DELETE'] | None = None\n    \"\"\"Optional HTTP method to use when loading the component.\"\"\"\n\n    type: _t.Literal['ServerLoad'] = 'ServerLoad'\n    \"\"\"The type of the component. Always 'ServerLoad'.\"\"\"\n\n\nclass Image(BaseModel, extra='forbid'):\n    \"\"\"Image container component.\"\"\"\n\n    src: str\n    \"\"\"The URL of the image to display.\"\"\"\n\n    alt: str | None = None\n    \"\"\"Optional alt text for the image.\"\"\"\n\n    width: str | int | None = None\n    \"\"\"Optional width used to display the image.\"\"\"\n\n    height: str | int | None = None\n    \"\"\"Optional height used to display the image.\"\"\"\n\n    referrer_policy: _t.Literal[\n        'no-referrer',\n        'no-referrer-when-downgrade',\n        'origin',\n        'origin-when-cross-origin',\n        'same-origin',\n        'strict-origin',\n        'strict-origin-when-cross-origin',\n        'unsafe-url',\n    ] | None = None\n    \"\"\"Optional referrer policy for the image. Specifies what information to send when fetching the image.\n\n    For more info, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy.\"\"\"\n\n    loading: _t.Literal['eager', 'lazy'] | None = None\n    \"\"\"Optional loading strategy for the image.\"\"\"\n\n    on_click: events.AnyEvent | None = None\n    \"\"\"Optional event to trigger when the image is clicked.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the image's HTML component.\"\"\"\n\n    type: _t.Literal['Image'] = 'Image'\n    \"\"\"The type of the component. Always 'Image'.\"\"\"\n\n\nclass Iframe(BaseModel, extra='forbid'):\n    \"\"\"Iframe component that displays content from a URL.\"\"\"\n\n    src: _p.HttpUrl\n    \"\"\"The URL of the content to display.\"\"\"\n\n    title: str | None = None\n    \"\"\"Optional title for the iframe.\"\"\"\n\n    width: str | int | None = None\n    \"\"\"Optional width used to display the iframe.\"\"\"\n\n    height: str | int | None = None\n    \"\"\"Optional height used to display the iframe.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the iframe's HTML component.\"\"\"\n\n    srcdoc: str | None = None\n    \"\"\"Optional HTML content to display in the iframe.\"\"\"\n\n    sandbox: str | None = None\n    \"\"\"Optional sandbox policy for the iframe. Specifies restrictions on the HTML content in the iframe.\"\"\"\n\n    type: _t.Literal['Iframe'] = 'Iframe'\n    \"\"\"The type of the component. Always 'Iframe'.\"\"\"\n\n\nclass Video(BaseModel, extra='forbid'):\n    \"\"\"Video component that displays a video or multiple videos.\"\"\"\n\n    sources: list[_p.AnyUrl]\n    \"\"\"List of URLs to the video sources.\"\"\"\n\n    autoplay: bool | None = None\n    \"\"\"Optional flag to enable autoplay for the video.\"\"\"\n\n    controls: bool | None = None\n    \"\"\"Optional flag to enable controls (pause, play, etc) for the video.\"\"\"\n\n    loop: bool | None = None\n    \"\"\"Optional flag to enable looping for the video.\"\"\"\n\n    muted: bool | None = None\n    \"\"\"Optional flag to mute the video.\"\"\"\n\n    poster: _p.AnyUrl | None = None\n    \"\"\"Optional URL to an image to display as the video poster (what is shown when the video is loading or until the user plays it).\"\"\"\n\n    width: str | int | None = None\n    \"\"\"Optional width used to display the video.\"\"\"\n\n    height: str | int | None = None\n    \"\"\"Optional height used to display the video.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the video's HTML component.\"\"\"\n\n    type: _t.Literal['Video'] = 'Video'\n    \"\"\"The type of the component. Always 'Video'.\"\"\"\n\n\nclass FireEvent(BaseModel, extra='forbid'):\n    \"\"\"Fire an event.\"\"\"\n\n    event: events.AnyEvent\n    \"\"\"The event to fire.\"\"\"\n\n    message: str | None = None\n    \"\"\"Optional message to display when the event is fired. Defaults to a blank message.\"\"\"\n\n    type: _t.Literal['FireEvent'] = 'FireEvent'\n    \"\"\"The type of the component. Always 'FireEvent'.\"\"\"\n\n\nclass Error(BaseModel, extra='forbid'):\n    \"\"\"Utility component used to display an error.\"\"\"\n\n    title: str\n    \"\"\"The title of the error.\"\"\"\n\n    description: str\n    \"\"\"The description of the error.\"\"\"\n\n    status_code: int | None = None\n    \"\"\"Optional status code of the error.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the error's HTML component.\"\"\"\n\n    type: _t.Literal['Error'] = 'Error'\n    \"\"\"The type of the component. Always 'Error'.\"\"\"\n\n    @classmethod\n    def __get_pydantic_json_schema__(\n        cls, core_schema: _core_schema.CoreSchema, handler: _p.GetJsonSchemaHandler\n    ) -> _t.Any:\n        # add `children` to the schema so it can be used in the client\n        json_schema = handler(core_schema)\n        schema_def = handler.resolve_ref_schema(json_schema)\n        schema_def['properties']['children'] = {'tsType': 'ReactNode'}\n        return json_schema\n\n\nclass Spinner(BaseModel, extra='forbid'):\n    \"\"\"Spinner component that displays a loading spinner.\"\"\"\n\n    text: str | None = None\n    \"\"\"Optional text to display with the spinner.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the spinner's HTML component.\"\"\"\n\n    type: _t.Literal['Spinner'] = 'Spinner'\n    \"\"\"The type of the component. Always 'Spinner'.\"\"\"\n\n\nclass Toast(BaseModel, defer_build=True, extra='forbid'):\n    \"\"\"Toast component that displays a toast message (small temporary message).\"\"\"\n\n    title: str\n    \"\"\"The title of the toast.\"\"\"\n\n    body: 'list[AnyComponent]'\n    \"\"\"List of components to render in the toast body.\"\"\"\n\n    # TODO: change these before the release (top left, center, end, etc). Can be done with the toast bug fix.\n    position: _t.Literal[\n        'top-start',\n        'top-center',\n        'top-end',\n        'middle-start',\n        'middle-center',\n        'middle-end',\n        'bottom-start',\n        'bottom-center',\n        'bottom-end',\n    ] | None = None\n    \"\"\"Optional position of the toast.\"\"\"\n\n    open_trigger: events.PageEvent | None = None\n    \"\"\"Optional event to trigger when the toast is opened.\"\"\"\n\n    open_context: events.ContextType | None = None\n    \"\"\"Optional context to pass to the open trigger event.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the toast's HTML component.\"\"\"\n\n    type: _t.Literal['Toast'] = 'Toast'\n    \"\"\"The type of the component. Always 'Toast'.\"\"\"\n\n\nclass Custom(BaseModel, extra='forbid'):\n    \"\"\"Custom component that allows for special data to be rendered.\"\"\"\n\n    data: _types.JsonData\n    \"\"\"The data to render in the custom component.\"\"\"\n\n    sub_type: str\n    \"\"\"The sub-type of the custom component.\"\"\"\n\n    library: str | None = None\n    \"\"\"Optional library to use for the custom component.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the custom component's HTML component.\"\"\"\n\n    type: _t.Literal['Custom'] = 'Custom'\n    \"\"\"The type of the component. Always 'Custom'.\"\"\"\n\n\nAnyComponent = _te.Annotated[\n    Text\n    | Paragraph\n    | PageTitle\n    | Div\n    | Page\n    | Heading\n    | Markdown\n    | Code\n    | Json\n    | Button\n    | Link\n    | LinkList\n    | Navbar\n    | Footer\n    | Modal\n    | ServerLoad\n    | Image\n    | Iframe\n    | Video\n    | FireEvent\n    | Error\n    | Spinner\n    | Custom\n    | Table\n    | Pagination\n    | Display\n    | Details\n    | Form\n    | FormField\n    | ModelForm\n    | Toast,\n    _p.Field(discriminator='type'),\n]\n\"\"\"Union of all components.\n\nPydantic discriminator field is set to 'type' to allow for efficient serialization and deserialization of the components.\"\"\"\n\n# Rebuild models:\nBaseForm.model_rebuild(_types_namespace={'AnyComponent': AnyComponent})\nForm.model_rebuild(_types_namespace={'AnyComponent': AnyComponent})\nModelForm.model_rebuild(_types_namespace={'AnyComponent': AnyComponent})\nDiv.model_rebuild(_types_namespace={'AnyComponent': AnyComponent})\nPage.model_rebuild(_types_namespace={'AnyComponent': AnyComponent})\nLink.model_rebuild(_types_namespace={'AnyComponent': AnyComponent})\nModal.model_rebuild(_types_namespace={'AnyComponent': AnyComponent})\nServerLoad.model_rebuild(_types_namespace={'AnyComponent': AnyComponent})\nToast.model_rebuild(_types_namespace={'AnyComponent': AnyComponent})\n"
  },
  {
    "path": "src/python-fastui/fastui/components/display.py",
    "content": "import enum\nimport typing as _t\nfrom abc import ABC\n\nimport annotated_types as _at\nimport pydantic\nimport typing_extensions as _te\nfrom pydantic_core import core_schema as _core_schema\n\nfrom .. import class_name as _class_name\nfrom .. import events\nfrom .. import types as _types\nfrom ..base import BaseModel\n\n__all__ = 'DisplayMode', 'DisplayLookup', 'Display', 'Details'\n\n\nclass DisplayMode(str, enum.Enum):\n    \"\"\"Display mode for a value.\"\"\"\n\n    auto = 'auto'  # default, same as None below\n    plain = 'plain'\n    datetime = 'datetime'\n    date = 'date'\n    duration = 'duration'\n    as_title = 'as_title'\n    markdown = 'markdown'\n    json = 'json'\n    inline_code = 'inline_code'\n    currency = 'currency'\n\n\nclass DisplayBase(BaseModel, ABC):\n    \"\"\"Base class for display components.\"\"\"\n\n    mode: DisplayMode | None = None\n    \"\"\"Display mode for the value.\"\"\"\n\n    title: str | None = None\n    \"\"\"Title to display for the value.\"\"\"\n\n    on_click: events.AnyEvent | None = None\n    \"\"\"Event to trigger when the value is clicked.\"\"\"\n\n\nclass DisplayLookup(DisplayBase, extra='forbid'):\n    \"\"\"Description of how to display a value looked up from data, either in a table or detail view.\"\"\"\n\n    field: str\n    \"\"\"Field to display.\"\"\"\n\n    table_width_percent: _te.Annotated[int, _at.Interval(ge=0, le=100)] | None = None\n    \"\"\"Percentage width - 0 to 100, specific to tables.\"\"\"\n\n\nclass Display(DisplayBase, extra='forbid'):\n    \"\"\"Description of how to display a value, either in a table or detail view.\"\"\"\n\n    value: _types.JsonData\n    \"\"\"Value to display.\"\"\"\n\n    type: _t.Literal['Display'] = 'Display'\n    \"\"\"The type of the component. Always 'Display'.\"\"\"\n\n\nclass Details(BaseModel, extra='forbid'):\n    \"\"\"Details associated with displaying a data model.\"\"\"\n\n    data: pydantic.SerializeAsAny[_types.DataModel]\n    \"\"\"Data model to display.\"\"\"\n\n    fields: list[DisplayLookup | Display] | None = None\n    \"\"\"Fields to display.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the details component.\"\"\"\n\n    type: _t.Literal['Details'] = 'Details'\n    \"\"\"The type of the component. Always 'Details'.\"\"\"\n\n    @pydantic.model_validator(mode='after')\n    def _fill_fields(self) -> _te.Self:\n        fields = {**type(self.data).model_fields, **type(self.data).model_computed_fields}\n\n        if self.fields is None:\n            self.fields = [DisplayLookup(field=name, title=field.title) for name, field in fields.items()]\n        else:\n            # add pydantic titles to fields that don't have them\n            for field in (c for c in self.fields if c.title is None):\n                if isinstance(field, DisplayLookup):\n                    pydantic_field = type(self.data).model_fields.get(field.field)\n                    if pydantic_field and pydantic_field.title:\n                        field.title = pydantic_field.title\n                elif isinstance(field, Display):\n                    field.title = field.title\n        return self\n\n    @classmethod\n    def __get_pydantic_json_schema__(\n        cls, core_schema: _core_schema.CoreSchema, handler: pydantic.GetJsonSchemaHandler\n    ) -> _t.Any:\n        json_schema = handler(core_schema)\n        schema_def = handler.resolve_ref_schema(json_schema)\n        schema_def['required'].append('fields')\n        return json_schema\n"
  },
  {
    "path": "src/python-fastui/fastui/components/forms.py",
    "content": "import typing as _t\nfrom abc import ABC\n\nimport pydantic\nimport typing_extensions as _te\n\nfrom .. import class_name as _class_name\nfrom .. import events, forms\nfrom .. import types as _types\nfrom ..base import BaseModel\n\nif _t.TYPE_CHECKING:\n    from . import AnyComponent\n\nInputHtmlType = _t.Literal['text', 'date', 'datetime-local', 'time', 'email', 'url', 'number', 'password', 'hidden']\n\n\nclass BaseFormField(BaseModel, ABC, defer_build=True):\n    \"\"\"Base class for form fields.\"\"\"\n\n    name: str\n    \"\"\"Name of the field.\"\"\"\n\n    title: list[str] | str\n    \"\"\"Title of the field to display. Can be a list of strings for multi-line titles.\"\"\"\n\n    required: bool = False\n    \"\"\"Whether the field is required. Defaults to False.\"\"\"\n\n    error: str | None = None\n    \"\"\"Error message to display if the field is invalid.\"\"\"\n\n    locked: bool = False\n    \"\"\"Whether the field is locked. Defaults to False.\"\"\"\n\n    description: str | None = None\n    \"\"\"Description of the field.\"\"\"\n\n    display_mode: _t.Literal['default', 'inline'] | None = None\n    \"\"\"Display mode for the field.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the field's HTML component.\"\"\"\n\n\nclass FormFieldInput(BaseFormField):\n    \"\"\"Form field for basic input.\"\"\"\n\n    html_type: InputHtmlType = 'text'\n    \"\"\"HTML input type for the field.\"\"\"\n\n    initial: str | float | None = None\n    \"\"\"Initial value for the field.\"\"\"\n\n    placeholder: str | None = None\n    \"\"\"Placeholder text for the field.\"\"\"\n\n    autocomplete: str | None = None\n    \"\"\"Autocomplete value for the field.\"\"\"\n\n    type: _t.Literal['FormFieldInput'] = 'FormFieldInput'\n    \"\"\"The type of the component. Always 'FormFieldInput'.\"\"\"\n\n\nclass FormFieldTextarea(BaseFormField):\n    \"\"\"Form field for text area input.\"\"\"\n\n    rows: int | None = None\n    \"\"\"Number of rows for the text area.\"\"\"\n\n    cols: int | None = None\n    \"\"\"Number of columns for the text area.\"\"\"\n\n    initial: str | None = None\n    \"\"\"Initial value for the text area.\"\"\"\n\n    placeholder: str | None = None\n    \"\"\"Placeholder text for the text area.\"\"\"\n\n    autocomplete: str | None = None\n    \"\"\"Autocomplete value for the text area.\"\"\"\n\n    type: _t.Literal['FormFieldTextarea'] = 'FormFieldTextarea'\n    \"\"\"The type of the component. Always 'FormFieldTextarea'.\"\"\"\n\n\nclass FormFieldBoolean(BaseFormField):\n    \"\"\"Form field for boolean input.\"\"\"\n\n    initial: bool | None = None\n    \"\"\"Initial value for the field.\"\"\"\n\n    mode: _t.Literal['checkbox', 'switch'] = 'checkbox'\n    \"\"\"Mode for the boolean field.\"\"\"\n\n    type: _t.Literal['FormFieldBoolean'] = 'FormFieldBoolean'\n    \"\"\"The type of the component. Always 'FormFieldBoolean'.\"\"\"\n\n\nclass FormFieldFile(BaseFormField):\n    \"\"\"Form field for file input.\"\"\"\n\n    multiple: bool | None = None\n    \"\"\"Whether multiple files can be selected.\"\"\"\n\n    accept: str | None = None\n    \"\"\"Accepted file types.\"\"\"\n\n    type: _t.Literal['FormFieldFile'] = 'FormFieldFile'\n    \"\"\"The type of the component. Always 'FormFieldFile'.\"\"\"\n\n\nclass FormFieldSelect(BaseFormField):\n    \"\"\"Form field for select input.\"\"\"\n\n    options: forms.SelectOptions\n    \"\"\"Options for the select field.\"\"\"\n\n    multiple: bool | None = None\n    \"\"\"Whether multiple options can be selected.\"\"\"\n\n    initial: list[str] | str | None = None\n    \"\"\"Initial value for the field.\"\"\"\n\n    vanilla: bool | None = None\n    \"\"\"Whether to use a vanilla (plain) select element.\"\"\"\n\n    placeholder: str | None = None\n    \"\"\"Placeholder text for the field.\"\"\"\n\n    autocomplete: str | None = None\n    \"\"\"Autocomplete value for the field.\"\"\"\n\n    type: _t.Literal['FormFieldSelect'] = 'FormFieldSelect'\n    \"\"\"The type of the component. Always 'FormFieldSelect'.\"\"\"\n\n\nclass FormFieldSelectSearch(BaseFormField):\n    \"\"\"Form field for searchable select input.\"\"\"\n\n    search_url: str\n    \"\"\"URL to search for options.\"\"\"\n\n    multiple: bool | None = None\n    \"\"\"Whether multiple options can be selected.\"\"\"\n\n    initial: forms.SelectOption | None = None\n    \"\"\"Initial value for the field.\"\"\"\n\n    debounce: int | None = None\n    \"\"\"Time in milliseconds to debounce requests by. Defaults to 300ms.\"\"\"\n\n    placeholder: str | None = None\n    \"\"\"Placeholder text for the field.\"\"\"\n\n    type: _t.Literal['FormFieldSelectSearch'] = 'FormFieldSelectSearch'\n    \"\"\"The type of the component. Always 'FormFieldSelectSearch'.\"\"\"\n\n\nFormField = (\n    FormFieldInput | FormFieldTextarea | FormFieldBoolean | FormFieldFile | FormFieldSelect | FormFieldSelectSearch\n)\n\n\"\"\"Union of all form field types.\"\"\"\n\n\nclass BaseForm(BaseModel, ABC, defer_build=True, extra='forbid'):\n    \"\"\"Base class for forms.\"\"\"\n\n    submit_url: str\n    \"\"\"URL to submit the form data to.\"\"\"\n\n    initial: dict[str, _types.JsonData] | None = None\n    \"\"\"Initial values for the form fields, mapping field names to values.\"\"\"\n\n    method: _t.Literal['POST', 'GOTO', 'GET'] = 'POST'\n    \"\"\"HTTP method to use for the form submission.\"\"\"\n\n    display_mode: _t.Literal['default', 'page', 'inline'] | None = None\n    \"\"\"Display mode for the form.\"\"\"\n\n    submit_on_change: bool | None = None\n    \"\"\"Whether to submit the form on change.\"\"\"\n\n    submit_trigger: events.PageEvent | None = None\n    \"\"\"Event to trigger form submission.\"\"\"\n\n    loading: 'list[AnyComponent] | None' = None\n    \"\"\"Components to display while the form is submitting.\"\"\"\n\n    footer: 'list[AnyComponent] | None' = None\n    \"\"\"Components to display in the form footer.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the form's HTML component.\"\"\"\n\n    @pydantic.model_validator(mode='after')\n    def default_footer(self) -> _te.Self:\n        if self.footer is None and self.display_mode == 'inline':\n            self.footer = []\n        return self\n\n\nclass Form(BaseForm, defer_build=True):\n    \"\"\"Form component.\"\"\"\n\n    form_fields: list[FormField]\n    \"\"\"List of form fields.\"\"\"\n\n    type: _t.Literal['Form'] = 'Form'\n    \"\"\"The type of the component. Always 'Form'.\"\"\"\n\n\nFormFieldsModel = _t.TypeVar('FormFieldsModel', bound=pydantic.BaseModel)\n\n# In Python 3.14, when evaluating the annotation of field `model`, `type` would refer\n# to the assigned value to the field `type` (of value `'ModelForm'`):\ntype_ = type\n\n\nclass ModelForm(BaseForm, defer_build=True):\n    \"\"\"Form component generated from a Pydantic model.\"\"\"\n\n    model: type_[pydantic.BaseModel] = pydantic.Field(exclude=True)\n    \"\"\"Pydantic model from which to generate the form.\"\"\"\n\n    type: _t.Literal['ModelForm'] = 'ModelForm'\n    \"\"\"The type of the component. Always 'ModelForm'.\"\"\"\n\n    @pydantic.computed_field(alias='formFields')\n    def form_fields(self) -> list[FormField]:\n        from ..json_schema import model_json_schema_to_fields\n\n        return model_json_schema_to_fields(self.model)\n"
  },
  {
    "path": "src/python-fastui/fastui/components/py.typed",
    "content": ""
  },
  {
    "path": "src/python-fastui/fastui/components/tables.py",
    "content": "import typing as _t\n\nimport pydantic\nimport typing_extensions as _te\nfrom pydantic_core import core_schema as _core_schema\n\nfrom .. import class_name as _class_name\nfrom .. import types as _types\nfrom ..base import BaseModel\nfrom . import display\n\n# TODO allow dataclasses and typed dicts here too\n\n\n# In Python 3.14, when evaluating the annotation of field `data_model`, `type` would refer\n# to the assigned value to the field `type` (of value `'Table'`):\ntype_ = type\n\n\nclass Table(BaseModel, extra='forbid'):\n    \"\"\"Table component.\"\"\"\n\n    data: _t.Sequence[pydantic.SerializeAsAny[_types.DataModel]]\n    \"\"\"Sequence of data models to display in the table.\"\"\"\n\n    columns: list[display.DisplayLookup] | None = None\n    \"\"\"List of columns to display in the table. If not provided, columns will be inferred from the data model.\"\"\"\n\n    data_model: type_[pydantic.BaseModel] | None = pydantic.Field(default=None, exclude=True)\n    \"\"\"Data model to use for the table. If not provided, the model will be inferred from the first data item.\"\"\"\n\n    no_data_message: str | None = None\n    \"\"\"Message to display when there is no data.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the paragraph's HTML component.\"\"\"\n\n    type: _t.Literal['Table'] = 'Table'\n    \"\"\"The type of the component. Always 'Table'.\"\"\"\n\n    @pydantic.model_validator(mode='after')\n    def _fill_columns(self) -> _te.Self:\n        if self.data_model:\n            data_model_type = self.data_model\n        else:\n            try:\n                data_model_type = type(self.data[0])\n            except IndexError:\n                raise ValueError('Cannot infer model from empty data, please set `Table(..., model=MyModel)`')\n\n        all_model_fields = {**data_model_type.model_fields, **data_model_type.model_computed_fields}\n        if self.columns is None:\n            self.columns = [\n                display.DisplayLookup(field=name, title=field.title) for name, field in all_model_fields.items()\n            ]\n        else:\n            # add pydantic titles to columns that don't have them\n            for column in (c for c in self.columns if c.title is None):\n                field = all_model_fields.get(column.field)\n                if field and field.title:\n                    column.title = field.title\n        return self\n\n    @classmethod\n    def __get_pydantic_json_schema__(\n        cls, core_schema: _core_schema.CoreSchema, handler: pydantic.GetJsonSchemaHandler\n    ) -> _t.Any:\n        json_schema = handler(core_schema)\n        schema_def = handler.resolve_ref_schema(json_schema)\n        # columns are filled by `_fill_columns`\n        schema_def['required'].append('columns')\n        return json_schema\n\n\nclass Pagination(BaseModel):\n    \"\"\"Pagination component to use with tables.\"\"\"\n\n    page: int\n    \"\"\"The current page number.\"\"\"\n\n    page_size: int\n    \"\"\"The number of items per page.\"\"\"\n\n    total: int\n    \"\"\"The total number of items.\"\"\"\n\n    page_query_param: str = 'page'\n    \"\"\"The query parameter to use for the page number.\"\"\"\n\n    class_name: _class_name.ClassNameField = None\n    \"\"\"Optional class name to apply to the pagination's HTML component.\"\"\"\n\n    type: _t.Literal['Pagination'] = 'Pagination'\n    \"\"\"The type of the component. Always 'Pagination'.\"\"\"\n\n    @pydantic.computed_field(alias='pageCount')\n    def page_count(self) -> int:\n        return (self.total - 1) // self.page_size + 1\n"
  },
  {
    "path": "src/python-fastui/fastui/dev.py",
    "content": "import asyncio\nimport os\nimport signal\nimport typing as _t\nfrom contextlib import asynccontextmanager\n\ntry:\n    from fastapi import FastAPI\n    from fastapi.responses import StreamingResponse\n    from starlette import types\nexcept ImportError as e:\n    raise ImportError('fastui.dev requires fastapi to be installed, install with `pip install fastui[fastapi]`') from e\n\n\ndef dev_fastapi_app(reload_path: str = '/api/__dev__/reload', **fastapi_kwargs) -> FastAPI:\n    dev_reload = DevReload(fastapi_kwargs.pop('lifespan', None))\n\n    app = FastAPI(lifespan=dev_reload.lifespan)\n    app.get(reload_path, include_in_schema=False)(dev_reload.dev_reload_endpoints)\n    return app\n\n\nclass DevReload:\n    def __init__(self, default_lifespan: types.Lifespan[FastAPI] | None):\n        self.default_lifespan = default_lifespan\n        self.stop = asyncio.Event()\n\n    @asynccontextmanager\n    async def lifespan(self, app: FastAPI):\n        signal.signal(signal.SIGTERM, self._on_signal)\n        if self.default_lifespan:\n            async with self.default_lifespan(app):\n                yield\n        else:\n            yield\n\n    async def dev_reload_endpoints(self):\n        return StreamingResponse(self.ping(), media_type='text/plain')\n\n    def _on_signal(self, *_args: _t.Any):\n        # print('setting stop', _args)\n        self.stop.set()\n\n    async def ping(self):\n        # print('connected', os.getpid())\n        yield b'fastui-dev-reload\\n'\n        yield b'.'\n        while True:\n            try:\n                await asyncio.wait_for(self.stop.wait(), timeout=2)\n            except asyncio.TimeoutError:\n                yield b'.'\n            else:\n                yield b'%d' % os.getpid()\n                break\n"
  },
  {
    "path": "src/python-fastui/fastui/events.py",
    "content": "from typing import Annotated, Literal\n\nfrom pydantic import Field\nfrom typing_extensions import TypeAliasType\n\nfrom .base import BaseModel\n\nContextType = TypeAliasType('ContextType', dict[str, str | int])\n\n\nclass PageEvent(BaseModel, defer_build=True):\n    name: str\n    push_path: str | None = None\n    context: ContextType | None = None\n    clear: bool | None = None\n    next_event: 'AnyEvent | None' = None\n    type: Literal['page'] = 'page'\n\n\nclass GoToEvent(BaseModel):\n    # can be a path or a full URL\n    url: str | None = None\n    query: dict[str, str | float | None] | None = None\n    target: Literal['_blank'] | None = None\n    type: Literal['go-to'] = 'go-to'\n\n\nclass BackEvent(BaseModel):\n    type: Literal['back'] = 'back'\n\n\nclass AuthEvent(BaseModel):\n    # False means clear the token and thereby logout the user\n    token: str | Literal[False]\n    url: str | None = None\n    type: Literal['auth'] = 'auth'\n\n\nAnyEvent = Annotated[PageEvent | GoToEvent | BackEvent | AuthEvent, Field(discriminator='type')]\n\nPageEvent.model_rebuild(_types_namespace={'AnyEvent': AnyEvent})\n"
  },
  {
    "path": "src/python-fastui/fastui/forms.py",
    "content": "import json\nimport typing as _t\nfrom itertools import groupby\nfrom mimetypes import MimeTypes\nfrom operator import itemgetter\n\nimport pydantic\nimport pydantic_core\nimport typing_extensions as _te\nfrom pydantic_core import core_schema\n\ntry:\n    import fastapi\n    from fastapi import params as fastapi_params\n    from starlette import datastructures as ds\nexcept ImportError as _e:\n    raise ImportError('fastui.dev requires fastapi to be installed, install with `pip install fastui[fastapi]`') from _e\n\nif _t.TYPE_CHECKING:\n    from . import json_schema\n\n__all__ = 'FastUIForm', 'fastui_form', 'FormFile', 'Textarea', 'SelectSearchResponse', 'SelectOption'\n\nFormModel = _t.TypeVar('FormModel', bound=pydantic.BaseModel)\n\n\nclass FastUIForm(_t.Generic[FormModel]):\n    \"\"\"\n    TODO mypy, pyright and pycharm don't understand the model type if this is used, is there a way to get it to work?\n    \"\"\"\n\n    def __class_getitem__(cls, model: type[FormModel]) -> fastapi_params.Depends:\n        return fastui_form(model)\n\n\ndef fastui_form(model: type[FormModel]) -> fastapi_params.Depends:\n    async def run_fastui_form(request: fastapi.Request):\n        async with request.form() as form_data:\n            model_data = unflatten(form_data)\n\n        try:\n            return model.model_validate(model_data)\n        except pydantic.ValidationError as e:\n            raise fastapi.HTTPException(\n                status_code=422,\n                detail={'form': e.errors(include_input=False, include_url=False, include_context=False)},\n            )\n\n    return fastapi.Depends(run_fastui_form)\n\n\nclass FormFile:\n    __slots__ = 'accept', 'max_size'\n\n    def __init__(self, accept: str | None = None, max_size: int | None = None):\n        self.accept = accept\n        self.max_size = max_size\n\n    def validate_single(self, input_value: _t.Any) -> ds.UploadFile:\n        if isinstance(input_value, ds.UploadFile):\n            file = input_value\n            self._validate_file(file)\n            return file\n        else:\n            raise pydantic_core.PydanticCustomError('not_file', 'Input is not a file')\n\n    def validate_multiple(self, input_value: _t.Any) -> list[ds.UploadFile]:\n        if isinstance(input_value, list):\n            return [self.validate_single(v) for v in input_value]\n        else:\n            return [self.validate_single(input_value)]\n\n    def _validate_file(self, file: ds.UploadFile) -> None:\n        \"\"\"\n        See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers\n        for details on what's allowed.\n        \"\"\"\n        if file.size == 0:\n            # FIXME is this right???\n            return\n\n        if self.max_size is not None and file.size is not None and file.size > self.max_size:\n            raise pydantic_core.PydanticCustomError(\n                'file_too_big',\n                'File size was {file_size}, exceeding maximum allowed size of {max_size}',\n                {\n                    'file_size': pydantic.ByteSize(file.size).human_readable(),\n                    'max_size': pydantic.ByteSize(self.max_size).human_readable(),\n                },\n            )\n\n        if self.accept is None:\n            return\n\n        for accept in self.accept.split(','):\n            accept = accept.strip()\n            if accept == '*/*':\n                return\n            elif accept.startswith('.'):\n                # this is a file extension\n                if file.filename and file.filename.endswith(accept):\n                    return\n\n            if content_type := get_content_type(file):\n                if accept.endswith('/*'):\n                    if content_type.startswith(accept[:-1]):\n                        return\n                elif content_type == accept:\n                    return\n\n        raise pydantic_core.PydanticCustomError(\n            'accept_mismatch',\n            (\n                'Uploaded file \"{filename}\" with content type \"{content_type}\" '\n                'does not match accept criteria \"{accept}\"'\n            ),\n            {'filename': file.filename, 'content_type': file.content_type, 'accept': self.accept},\n        )\n\n    def __get_pydantic_core_schema__(self, source_type: type[_t.Any], *_args) -> core_schema.CoreSchema:\n        if _t.get_origin(source_type) is list:\n            args = _t.get_args(source_type)\n            if len(args) == 1 and issubclass(args[0], ds.UploadFile):\n                return core_schema.no_info_plain_validator_function(self.validate_multiple)\n        elif issubclass(source_type, ds.UploadFile):\n            return core_schema.no_info_plain_validator_function(self.validate_single)\n\n        raise TypeError(f'FormFile can only be used with `UploadFile` or `list[UploadFile]`, not {source_type}')\n\n    def __get_pydantic_json_schema__(self, core_schema_: core_schema.CoreSchema, *_args) -> 'json_schema.JsonSchemaAny':\n        from . import json_schema\n\n        s = json_schema.JsonSchemaFile(type='string', format='binary')\n        if self.accept:\n            s['accept'] = self.accept\n\n        function = core_schema_.get('function', {}).get('function')\n        if function and function.__name__ == 'validate_multiple':\n            s = json_schema.JsonSchemaArray(type='array', items=s)\n        return s\n\n    def __repr__(self):\n        return f'FormFile(accept={self.accept!r})'\n\n\n_mime_types = MimeTypes()\n\n\ndef get_content_type(file: ds.UploadFile) -> str | None:\n    if file.content_type:\n        return file.content_type\n    elif file.filename:\n        return _mime_types.guess_type(file.filename)[0]\n\n\nclass SelectOption(_te.TypedDict):\n    value: str\n    label: str\n\n\nclass SelectGroup(_te.TypedDict):\n    label: str\n    options: list[SelectOption]\n\n\nSelectOptions = _te.TypeAliasType('SelectOptions', list[SelectOption] | list[SelectGroup])\n\n\nclass SelectSearchResponse(pydantic.BaseModel):\n    options: SelectOptions\n\n\nNestedDict: _te.TypeAlias = 'dict[str | int, NestedDict | str | list[str] | ds.UploadFile | list[ds.UploadFile]]'\n\n\ndef unflatten(form_data: ds.FormData) -> NestedDict:\n    \"\"\"\n    Unflatten a `FormData` dict into a nested dict.\n\n    Also omit empty strings, this might be a bit controversial, but it helps in many scenarios, e.g. a select\n    which hasn't been updated. It also avoids empty values for string inputs that haven't been fill in.\n    \"\"\"\n    result_dict: NestedDict = {}\n    for key, g in groupby(form_data.multi_items(), itemgetter(0)):\n        values = [v for _, v in g]\n        if values == ['']:\n            continue\n\n        d: dict[str | int, _t.Any] = result_dict\n\n        *path, last_key = name_to_loc(key)\n        for part in path:\n            if part not in d:\n                d[part] = {}\n            d = d[part]\n\n        if len(values) == 1:\n            d[last_key] = values[0]\n        else:\n            d[last_key] = values\n\n    # this logic takes care of converting `dict[int, str]` to `list[str]`\n    # we recursively process each dict in `result_dict` and convert it to a list if all keys are ints\n    dicts = [result_dict]\n    while dicts:\n        d = dicts.pop()\n        for key, value in d.items():\n            if isinstance(value, dict):\n                if all(isinstance(k, int) for k in value):\n                    # sort key-value pairs based on the keys, then take just the values as a list\n                    d[key] = [v for _, v in sorted(value.items())]\n                else:\n                    dicts.append(value)\n\n    return result_dict\n\n\ndef name_to_loc(name: str) -> 'json_schema.SchemeLocation':\n    if name.startswith('['):\n        return json.loads(name)\n    else:\n        loc: 'json_schema.SchemeLocation' = []\n        for part in name.split('.'):\n            if part.isdigit():\n                loc.append(int(part))\n            else:\n                loc.append(part)\n        return loc\n\n\n# Use uppercase for consistency with pydantic.Field, which is also a function\ndef Textarea(rows: int | None = None, cols: int | None = None) -> _t.Any:  # N802\n    return pydantic.Field(json_schema_extra={'format': 'textarea', 'rows': rows, 'cols': cols})\n"
  },
  {
    "path": "src/python-fastui/fastui/generate_typescript.py",
    "content": "from __future__ import annotations as _annotations\n\nimport re\nimport subprocess\nfrom pathlib import Path\nfrom typing import Any, cast\n\nfrom pydantic import ImportString, TypeAdapter\nfrom pydantic.json_schema import GenerateJsonSchema, JsonSchemaValue\nfrom pydantic_core import core_schema, to_json\n\n\ndef main(python_object_str: str, typescript_output_file: Path):  # pragma: no cover\n    root_model = TypeAdapter(ImportString).validate_python(python_object_str)\n    json_schema = generate_json_schema(root_model)\n    json_schema_file = Path('fastui-json-schema.json')\n    json_schema_file.write_bytes(to_json(json_schema, indent=2))\n    # NOTE: `json-schema-to-typescript` generates ugly schemas\n    # (https://github.com/bcherny/json-schema-to-typescript/issues/193).\n    # Note sure what the way forward is.\n    json2ts(json_schema_file, typescript_output_file)\n\n\ndef generate_json_schema(root_model: Any) -> JsonSchemaValue:\n    fastui_schema = TypeAdapter(root_model).json_schema(\n        by_alias=True, mode='serialization', schema_generator=CustomGenerateJsonSchema\n    )\n    # the following post-processing is a workaround for\n    # https://github.com/pydantic/pydantic/issues/8320\n    any_comp_def = fastui_schema['$defs']['Div']['properties']['components']['items'].copy()\n    any_comp_ref = {'$ref': '#/$defs/FastProps'}\n\n    def replace_any_comp(value: Any) -> Any:\n        if isinstance(value, dict):\n            if value == any_comp_def:\n                return any_comp_ref\n            else:\n                return {k: replace_any_comp(v) for k, v in value.items()}\n        elif isinstance(value, list):\n            return [replace_any_comp(v) for v in value]\n        else:\n            return value\n\n    fastui_schema['items'] = any_comp_ref\n    fastui_schema = replace_any_comp(fastui_schema)\n    fastui_schema['$defs']['FastProps'] = any_comp_def\n    fastui_schema.pop('description')\n    return fastui_schema\n\n\nclass CustomGenerateJsonSchema(GenerateJsonSchema):\n    def field_title_should_be_set(self, schema) -> bool:\n        return False\n\n    def default_schema(self, schema: core_schema.WithDefaultSchema) -> JsonSchemaValue:\n        inner = schema['schema']\n        if is_type_schema(schema):\n            return self.generate_inner(inner)\n\n        # if inner.get('type') == 'nullable' and inner.get('ref', '').startswith('fastui.class_name.ClassName:'):\n        #     return self.generate_inner(inner)\n\n        return super().default_schema(schema)\n\n    def field_is_required(\n        self,\n        field: core_schema.ModelField | core_schema.DataclassField | core_schema.TypedDictField,\n        total: bool,\n    ) -> bool:\n        inner = field['schema']\n        if inner['type'] == 'default' and is_type_schema(cast(core_schema.WithDefaultSchema, inner)):\n            return True\n        else:\n            return super().field_is_required(field, total)\n\n    def nullable_schema(self, schema: core_schema.NullableSchema) -> JsonSchemaValue:\n        null_schema = {'type': 'null'}\n        inner_json_schema = self.generate_inner(schema['schema'])\n\n        if inner_json_schema == null_schema:\n            return null_schema\n        else:\n            # since we use `exclude_none=True`, field can't be null\n            return inner_json_schema\n\n    def tagged_union_schema(self, schema: core_schema.TaggedUnionSchema) -> JsonSchemaValue:\n        if schema['discriminator'] == 'type':\n            if 'go-to' in schema['choices']:\n                schema['ref'] = 'fastui.events.AnyEvent'\n        return super().tagged_union_schema(schema)\n\n\ndef is_type_schema(schema: core_schema.WithDefaultSchema) -> bool:\n    inner = schema['schema']\n    if inner['type'] == 'literal':\n        expected = cast(core_schema.LiteralSchema, inner)['expected']\n        if len(expected) == 1 and expected[0] == schema.get('default', object()):\n            return True\n    return False\n\n\nTS_PREFIX = b\"\"\"\\\n/**\n * This file was automatically generated by json-schema-to-typescript.\n * DO NOT MODIFY IT BY HAND. Instead, modify python types, then run\n * `fastui generate <python-object> <typescript-output-file>`.\n */\"\"\"\n\n\ndef json2ts(input_file: Path, output_file: Path):  # pragma: no cover\n    args = (\n        'npx',\n        'json2ts',\n        str(input_file),\n        str(output_file),\n        '--additionalProperties',\n        'false',\n        '--no-style.semi',\n        '--style.singleQuote',\n        '--no-unknownAny',\n    )\n    try:\n        subprocess.run(args, check=True)\n    except (subprocess.CalledProcessError, FileNotFoundError) as e:\n        raise RuntimeError(\n            \"Failed to run json2ts, you'll need to install `npx` and `json-schema-to-typescript`, \"\n            f\"then run the command:\\n\\n    {' '.join(args)}\\n\\n\"\n        ) from e\n    else:\n        assert output_file.is_file()\n        # remove the root list type that we don't need\n        output = (\n            output_file.read_bytes()\n            .replace(b'export type FastUI = FastProps[]\\n', b'')\n            .replace(b'/* eslint-disable */\\n', b'')\n        )\n        output = re.sub(rb'/\\*\\*\\s+\\* This file was automatically generated.+?\\*/', TS_PREFIX, output, flags=re.DOTALL)\n        output_file.write_bytes(output)\n        input_file.unlink()\n"
  },
  {
    "path": "src/python-fastui/fastui/json_schema.py",
    "content": "import json\nimport re\nimport typing as _t\n\nimport typing_extensions as _ta\nfrom pydantic import BaseModel\n\nfrom .components.forms import (\n    FormField,\n    FormFieldBoolean,\n    FormFieldFile,\n    FormFieldInput,\n    FormFieldSelect,\n    FormFieldSelectSearch,\n    FormFieldTextarea,\n    InputHtmlType,\n)\n\nif _t.TYPE_CHECKING:\n    from .forms import SelectOption\nelse:\n    SelectOption = dict\n\n__all__ = 'model_json_schema_to_fields', 'SchemeLocation'\n\n\ndef model_json_schema_to_fields(model: type[BaseModel]) -> list[FormField]:\n    schema = _t.cast(JsonSchemaObject, model.model_json_schema())\n    defs = schema.get('$defs', {})\n    return list(json_schema_obj_to_fields(schema, [], [], defs))\n\n\nJsonSchemaInput: _ta.TypeAlias = (\n    'JsonSchemaString | JsonSchemaStringEnum | JsonSchemaFile | JsonSchemaTextarea | JsonSchemaInt | JsonSchemaNumber'\n)\nJsonSchemaField: _ta.TypeAlias = 'JsonSchemaInput | JsonSchemaBool'\nJsonSchemaConcrete: _ta.TypeAlias = 'JsonSchemaField | JsonSchemaArray | JsonSchemaObject'\nJsonSchemaAny: _ta.TypeAlias = 'JsonSchemaConcrete | JsonSchemaAnyOf | JsonSchemaAllOf | JsonSchemaRef'\n\n\nclass JsonSchemaBase(_t.TypedDict, total=False):\n    title: str\n    description: str\n\n\nclass JsonSchemaString(JsonSchemaBase):\n    type: _ta.Required[_t.Literal['string']]\n    default: str\n    format: _t.Literal['date', 'date-time', 'time', 'email', 'uri', 'uuid', 'password']\n\n\nclass JsonSchemaStringEnum(JsonSchemaBase, total=False):\n    type: _ta.Required[_t.Literal['string']]\n    enum: _ta.Required[list[str]]\n    default: str\n    placeholder: str\n    enum_labels: dict[str, str]\n\n\nclass JsonSchemaStringSearch(JsonSchemaBase, total=False):\n    type: _ta.Required[_t.Literal['string']]\n    search_url: _ta.Required[str]\n    placeholder: str\n    initial: SelectOption\n\n\nclass JsonSchemaFile(JsonSchemaBase, total=False):\n    type: _ta.Required[_t.Literal['string']]\n    format: _ta.Required[_t.Literal['binary']]\n    accept: str\n\n\nclass JsonSchemaTextarea(JsonSchemaBase, total=False):\n    type: _ta.Required[_t.Literal['string']]\n    format: _ta.Required[_t.Literal['textarea']]\n    rows: int\n    cols: int\n    default: str\n    placeholder: str\n\n\nclass JsonSchemaBool(JsonSchemaBase, total=False):\n    type: _ta.Required[_t.Literal['boolean']]\n    default: bool\n    mode: _t.Literal['checkbox', 'switch']\n\n\nclass JsonSchemaInt(JsonSchemaBase, total=False):\n    type: _ta.Required[_t.Literal['integer']]\n    default: int\n    minimum: int\n    exclusiveMinimum: int\n    maximum: int\n    exclusiveMaximum: int\n    multipleOf: int\n\n\nclass JsonSchemaNumber(JsonSchemaBase, total=False):\n    type: _ta.Required[_t.Literal['number']]\n    default: float\n    minimum: float\n    exclusiveMinimum: float\n    maximum: float\n    exclusiveMaximum: float\n    multipleOf: float\n\n\nclass JsonSchemaArray(JsonSchemaBase, total=False):\n    type: _ta.Required[_t.Literal['array']]\n    uniqueItems: bool\n    minItems: int\n    maxItems: int\n    prefixItems: list[JsonSchemaAny]\n    items: JsonSchemaAny\n    search_url: str\n    placeholder: str\n\n\nJsonSchemaDefs: _ta.TypeAlias = 'dict[str, JsonSchemaConcrete]'\nJsonSchemaObject = _t.TypedDict(\n    'JsonSchemaObject',\n    {\n        'type': _ta.Required[_t.Literal['object']],\n        'properties': dict[str, JsonSchemaAny],\n        '$defs': JsonSchemaDefs,\n        'required': list[str],\n        'title': str,\n        'description': str,\n    },\n    total=False,\n)\n\n\nclass JsonSchemaNull(JsonSchemaBase):\n    type: _t.Literal['null']\n\n\nclass JsonSchemaAnyOf(JsonSchemaBase):\n    anyOf: list[JsonSchemaAny]\n\n\nclass JsonSchemaAllOf(JsonSchemaBase):\n    allOf: list[JsonSchemaAny]\n\n\nJsonSchemaRef = _t.TypedDict('JsonSchemaRef', {'$ref': str})\n\nSchemeLocation: _ta.TypeAlias = 'list[str | int]'\n\n\ndef json_schema_obj_to_fields(\n    schema: JsonSchemaObject, loc: SchemeLocation, title: list[str], defs: JsonSchemaDefs\n) -> _t.Iterable[FormField]:\n    required = set(schema.get('required', []))\n    if properties := schema.get('properties'):\n        for key, value in properties.items():\n            yield from json_schema_any_to_fields(value, loc + [key], title, key in required, defs)\n\n\ndef json_schema_any_to_fields(\n    schema: JsonSchemaAny, loc: SchemeLocation, title: list[str], required: bool, defs: JsonSchemaDefs\n) -> _t.Iterable[FormField]:\n    dereferenced, required = deference_json_schema(schema, defs, required)\n    title = title + [schema.get('title', dereferenced.get('title', loc_to_title(loc)))]\n    description = schema.get('description', dereferenced.get('description'))\n\n    if schema_is_field(dereferenced):\n        yield json_schema_field_to_field(dereferenced, loc, title, description, required)\n    elif schema_is_array(dereferenced):\n        yield from json_schema_array_to_fields(dereferenced, loc, title, description, required, defs)\n    else:\n        assert schema_is_object(dereferenced), f'Unexpected schema type {dereferenced}'\n\n        yield from json_schema_obj_to_fields(dereferenced, loc, title, defs)\n\n\ndef json_schema_field_to_field(\n    schema: JsonSchemaField,\n    loc: SchemeLocation,\n    title: list[str],\n    description: str | None,\n    required: bool,\n) -> FormField:\n    name = loc_to_name(loc)\n    if schema['type'] == 'boolean':\n        return FormFieldBoolean(\n            name=name,\n            title=title,\n            required=required,\n            initial=schema.get('default'),\n            description=description,\n            mode=schema.get('mode', 'checkbox'),\n        )\n    elif field := special_string_field(schema, name, title, description, required, False):\n        return field\n    else:\n        return FormFieldInput(\n            name=name,\n            title=title,\n            html_type=input_html_type(schema),\n            required=required,\n            initial=schema.get('default'),\n            autocomplete=schema.get('autocomplete'),\n            description=schema.get('description'),\n            placeholder=schema.get('placeholder'),\n        )\n\n\ndef loc_to_title(loc: SchemeLocation) -> str:\n    return as_title(loc[-1])\n\n\ndef json_schema_array_to_fields(\n    schema: JsonSchemaArray,\n    loc: SchemeLocation,\n    title: list[str],\n    description: str | None,\n    required: bool,\n    defs: JsonSchemaDefs,\n) -> _t.Iterable[FormField]:\n    items_schema = schema.get('items')\n    if items_schema:\n        items_schema, required = deference_json_schema(items_schema, defs, required)\n        for field_name in 'search_url', 'placeholder':\n            if value := schema.get(field_name):\n                items_schema[field_name] = value  # type: ignore\n        if field := special_string_field(items_schema, loc_to_name(loc), title, description, required, True):\n            yield field\n            return\n\n    # for fixed length tuples (min_items == max_items), where all items are required,\n    # we \"inline\" the fields into the list of form fields\n    if (min_items := schema.get('minItems')) and min_items == schema.get('maxItems'):\n        if items := schema.get('prefixItems'):\n            for i, item in enumerate(items):\n                fields = list(json_schema_any_to_fields(item, loc + [i], title, required, defs))\n                if any(not f.required for f in fields):\n                    raise NotImplementedError(\n                        'Tuples with optional fields are not yet supported, '\n                        'see https://github.com/pydantic/FastUI/pull/52'\n                    )\n                yield from fields\n            return\n\n    raise NotImplementedError('Array fields are not fully supported, see https://github.com/pydantic/FastUI/pull/52')\n\n\ndef special_string_field(\n    schema: JsonSchemaConcrete,\n    name: str,\n    title: list[str],\n    description: str | None,\n    required: bool,\n    multiple: bool,\n) -> FormField | None:\n    if schema['type'] == 'string':\n        if schema.get('format') == 'binary':\n            return FormFieldFile(\n                name=name,\n                title=title,\n                required=required,\n                multiple=multiple,\n                accept=schema.get('accept'),\n                description=description,\n            )\n        elif schema.get('format') == 'textarea':\n            return FormFieldTextarea(\n                name=name,\n                title=title,\n                required=required,\n                rows=schema.get('rows'),\n                cols=schema.get('cols'),\n                placeholder=schema.get('placeholder'),\n                initial=schema.get('initial'),\n                description=description,\n                autocomplete=schema.get('autocomplete'),\n            )\n        elif enum := schema.get('enum'):\n            enum_labels = schema.get('enum_labels', {})\n            return FormFieldSelect(\n                name=name,\n                title=title,\n                placeholder=schema.get('placeholder'),\n                required=required,\n                multiple=multiple,\n                options=[SelectOption(value=v, label=enum_labels.get(v) or as_title(v)) for v in enum],\n                initial=schema.get('default'),\n                description=description,\n                autocomplete=schema.get('autocomplete'),\n            )\n        elif search_url := schema.get('search_url'):\n            return FormFieldSelectSearch(\n                search_url=search_url,\n                name=name,\n                title=title,\n                placeholder=schema.get('placeholder'),\n                required=required,\n                multiple=multiple,\n                initial=schema.get('initial'),\n                description=description,\n            )\n\n\ndef loc_to_name(loc: SchemeLocation) -> str:\n    \"\"\"\n    Convert a loc to a string if any item contains a '.' or the first item starts with '[' then encode with JSON,\n    otherwise join with '.'.\n\n    The sister method `name_to_loc` is in `form_extra.py`.\n    \"\"\"\n    if any(isinstance(v, str) and '.' in v for v in loc):\n        return json.dumps(loc)\n    elif isinstance(loc[0], str) and loc[0].startswith('['):\n        return json.dumps(loc)\n    else:\n        return '.'.join(str(v) for v in loc)\n\n\ndef deference_json_schema(\n    schema: JsonSchemaAny, defs: JsonSchemaDefs, required: bool\n) -> tuple[JsonSchemaConcrete, bool]:\n    \"\"\"\n    Convert a schema which might be a reference or union to a concrete schema.\n    \"\"\"\n    if ref := schema.get('$ref'):\n        defs = defs or {}\n        def_schema = defs[ref.rsplit('/')[-1]]\n        if def_schema is None:\n            raise ValueError(f'Invalid $ref \"{ref}\", not found in {defs}')\n        else:\n            return def_schema.copy(), required  # clone dict to avoid attribute leakage via shared schema.\n    elif any_of := schema.get('anyOf'):\n        if len(any_of) == 2 and sum(s.get('type') == 'null' for s in any_of) == 1:\n            # If anyOf is a single type and null, then it is optional\n            not_null_schema = next(s for s in any_of if s.get('type') != 'null')\n\n            # copy everything except `anyOf` across to the new schema\n            # TODO is this right?\n            for key, value in schema.items():  # type: ignore\n                if key not in {'anyOf'}:\n                    not_null_schema[key] = value  # type: ignore\n\n            return deference_json_schema(not_null_schema, defs, False)\n        else:\n            raise NotImplementedError('`anyOf` schemas which are not simply `X | None` are not yet supported')\n    elif all_of := schema.get('allOf'):\n        all_of = _t.cast(list[JsonSchemaAny], all_of)\n        if len(all_of) == 1:\n            new_schema, required = deference_json_schema(all_of[0], defs, required)\n            new_schema.update({k: v for k, v in schema.items() if k != 'allOf'})  # type: ignore\n            return new_schema, required\n        else:\n            raise NotImplementedError('`allOf` schemas with more than 1 choice are not yet supported')\n    else:\n        return _t.cast(JsonSchemaConcrete, schema), required\n\n\ndef as_title(s: _t.Any) -> str:\n    return re.sub(r'[\\-_]', ' ', str(s)).title()\n\n\ntype_lookup: dict[str, InputHtmlType] = {\n    'string': 'text',\n    'string-date': 'date',\n    'string-date-time': 'datetime-local',\n    'string-time': 'time',\n    'string-email': 'email',\n    'string-uri': 'url',\n    'string-uuid': 'text',\n    'string-password': 'password',\n    'number': 'number',\n    'integer': 'number',\n}\n\n\ndef input_html_type(schema: JsonSchemaField) -> InputHtmlType:\n    \"\"\"\n    Convert a schema into an HTML type\n    \"\"\"\n    key = schema['type']\n    if key == 'string':\n        if string_format := schema.get('format'):\n            key = f'string-{string_format}'\n\n    try:\n        return type_lookup[key]\n    except KeyError as e:\n        raise ValueError(f'Unknown schema: {schema}') from e\n\n\ndef schema_is_field(schema: JsonSchemaConcrete) -> _ta.TypeGuard[JsonSchemaField]:\n    \"\"\"\n    Determine if a schema is a field `JsonSchemaField`\n    \"\"\"\n    return schema['type'] in {'string', 'number', 'integer', 'boolean'}\n\n\ndef schema_is_array(schema: JsonSchemaConcrete) -> _ta.TypeGuard[JsonSchemaArray]:\n    \"\"\"\n    Determine if a schema is an array `JsonSchemaArray`\n    \"\"\"\n    return schema['type'] == 'array'\n\n\ndef schema_is_object(schema: JsonSchemaConcrete) -> _ta.TypeGuard[JsonSchemaObject]:\n    \"\"\"\n    Determine if a schema is an object `JsonSchemaObject`\n    \"\"\"\n    return schema['type'] == 'object'\n"
  },
  {
    "path": "src/python-fastui/fastui/py.typed",
    "content": ""
  },
  {
    "path": "src/python-fastui/fastui/types.py",
    "content": "import typing as _t\n\nimport pydantic\nimport typing_extensions as _te\nfrom pydantic.json_schema import CoreRef, GenerateJsonSchema, JsonRef\nfrom pydantic_core import core_schema\n\nIS_PYDANTIC_211_OR_GREATER = tuple(int(v) for v in pydantic.VERSION.split('.')[:2]) >= (2, 11)\n\n\n# TODO: replace with https://docs.pydantic.dev/dev/api/types/#pydantic.types.JsonValue, maybe?\nclass JsonDataSchema:\n    @staticmethod\n    def __get_pydantic_json_schema__(\n        _core_schema: core_schema.CoreSchema, handler: pydantic.GetJsonSchemaHandler\n    ) -> _t.Any:\n        json_data_schema = core_schema.union_schema(\n            [\n                core_schema.str_schema(),\n                core_schema.float_schema(),\n                core_schema.bool_schema(),\n                core_schema.none_schema(),\n                core_schema.list_schema(core_schema.definition_reference_schema('JsonData')),\n                core_schema.dict_schema(core_schema.str_schema(), core_schema.definition_reference_schema('JsonData')),\n            ],\n            ref='JsonData',\n        )\n        rv = handler(json_data_schema)\n        if IS_PYDANTIC_211_OR_GREATER:\n            # Terrible hack. This is mimicking `GenerateJsonSchema.generate_inner.<locals>.populate_defs()`,\n            # which used to be called in some place until 2.11, where the call was removed by\n            # https://github.com/pydantic/pydantic/pull/11475.\n            # The approach taken by this `JsonDataSchema` annotation (manually setting references) isn't viable,\n            # but Pydantic is missing proper semantics on the behavior of core schema references\n            gen_js_schema = _t.cast(GenerateJsonSchema, handler.generate_json_schema)  # type: ignore\n            defs_ref, ref_json_schema = gen_js_schema.get_cache_defs_ref_schema(CoreRef('JsonData'))\n            json_ref = JsonRef(ref_json_schema['$ref'])\n            if rv.get('$ref', None) != json_ref:\n                gen_js_schema.definitions[defs_ref] = rv\n            rv = ref_json_schema\n        return rv\n\n\nJsonData = _te.Annotated[_t.Any, JsonDataSchema()]\n\n\nclass PydanticModelSchema:\n    @staticmethod\n    def __get_pydantic_json_schema__(\n        _core_schema: core_schema.CoreSchema, handler: pydantic.GetJsonSchemaHandler\n    ) -> _t.Any:\n        model_json_schema = core_schema.dict_schema(\n            core_schema.str_schema(),\n            core_schema.definition_reference_schema('JsonData'),\n            ref='DataModel',\n        )\n        rv = handler(model_json_schema)\n        if IS_PYDANTIC_211_OR_GREATER:\n            # Terrible hack. This is mimicking `GenerateJsonSchema.generate_inner.<locals>.populate_defs()`,\n            # which used to be called in some place until 2.11, where the call was removed by\n            # https://github.com/pydantic/pydantic/pull/11475.\n            # The approach taken by this `PydanticModelSchema` annotation (manually setting references) isn't viable,\n            # but Pydantic is missing proper semantics on the behavior of core schema references\n            gen_js_schema = _t.cast(GenerateJsonSchema, handler.generate_json_schema)  # type: ignore\n            defs_ref, ref_json_schema = gen_js_schema.get_cache_defs_ref_schema(CoreRef('DataModel'))\n            json_ref = JsonRef(ref_json_schema['$ref'])\n            if rv.get('$ref', None) != json_ref:\n                gen_js_schema.definitions[defs_ref] = rv\n            rv = ref_json_schema\n        return rv\n\n\nDataModel = _te.Annotated[pydantic.BaseModel, PydanticModelSchema()]\nDataModelGeneric = _t.TypeVar('DataModelGeneric', bound=DataModel)\n"
  },
  {
    "path": "src/python-fastui/pyproject.toml",
    "content": "[build-system]\nrequires = [\"hatchling\"]\nbuild-backend = \"hatchling.build\"\n\n[tool.hatch.version]\npath = \"fastui/__init__.py\"\n\n[project]\nname = \"fastui\"\ndescription = \"Build better UIs faster.\"\nauthors = [{ name = \"Samuel Colvin\", email = \"s@muelcolvin.com\" }]\nlicense = \"MIT\"\nreadme = \"README.md\"\nclassifiers = [\n    \"Development Status :: 4 - Beta\",\n    \"Topic :: Internet\",\n    \"License :: OSI Approved :: MIT License\",\n    \"Programming Language :: Python :: 3\",\n    'Programming Language :: Python :: 3 :: Only',\n    'Programming Language :: Python :: 3.10',\n    'Programming Language :: Python :: 3.11',\n    'Programming Language :: Python :: 3.12',\n    'Programming Language :: Python :: 3.13',\n    'Programming Language :: Python :: 3.14',\n    \"Intended Audience :: Developers\",\n    \"Intended Audience :: Information Technology\",\n    \"Framework :: Pydantic :: 2\",\n    \"Framework :: FastAPI\",\n]\nrequires-python = \">=3.10\"\ndependencies = [\"pydantic[email]>=2.8.0\"]\ndynamic = [\"version\"]\n\n[project.optional-dependencies]\nfastapi = [\n    \"fastapi>=0.104\",\n    \"python-multipart>=0.0.6\",\n]\n\n[project.urls]\nHomepage = \"https://github.com/pydantic/FastUI\"\n\n[project.scripts]\nfastui = \"fastui.__main__:cli\"\n"
  },
  {
    "path": "src/python-fastui/requirements/all.txt",
    "content": "-r ./lint.txt\n-r ./test.txt\n-r ./pyproject.txt\nuvicorn[standard]\nhttpx\n"
  },
  {
    "path": "src/python-fastui/requirements/lint.in",
    "content": "ruff\npyright\n"
  },
  {
    "path": "src/python-fastui/requirements/lint.txt",
    "content": "#\n# This file is autogenerated by pip-compile with Python 3.11\n# by the following command:\n#\n#    pip-compile --output-file=src/python-fastui/requirements/lint.txt --strip-extras src/python-fastui/requirements/lint.in\n#\nnodeenv==1.8.0\n    # via pyright\npyright==1.1.335\n    # via -r src/python-fastui/requirements/lint.in\nruff==0.1.5\n    # via -r src/python-fastui/requirements/lint.in\n\n# The following packages are considered to be unsafe in a requirements file:\n# setuptools\n"
  },
  {
    "path": "src/python-fastui/requirements/pyproject.txt",
    "content": "#\n# This file is autogenerated by pip-compile with Python 3.14\n# by the following command:\n#\n#    pip-compile --constraint=src/python-fastui/requirements/lint.txt --extra=fastapi --output-file=src/python-fastui/requirements/pyproject.txt --strip-extras src/python-fastui/pyproject.toml\n#\nannotated-doc==0.0.3\n    # via fastapi\nannotated-types==0.6.0\n    # via pydantic\nanyio==4.11.0\n    # via starlette\ndnspython==2.5.0\n    # via email-validator\nemail-validator==2.1.0.post1\n    # via pydantic\nfastapi==0.120.1\n    # via fastui (src/python-fastui/pyproject.toml)\nidna==3.11\n    # via\n    #   anyio\n    #   email-validator\npydantic==2.12.3\n    # via\n    #   fastapi\n    #   fastui (src/python-fastui/pyproject.toml)\npydantic-core==2.41.4\n    # via pydantic\npython-multipart==0.0.7\n    # via fastui (src/python-fastui/pyproject.toml)\nsniffio==1.3.1\n    # via anyio\nstarlette==0.48.0\n    # via fastapi\ntyping-extensions==4.15.0\n    # via\n    #   fastapi\n    #   pydantic\n    #   pydantic-core\n    #   typing-inspection\ntyping-inspection==0.4.2\n    # via pydantic\n"
  },
  {
    "path": "src/python-fastui/requirements/render.txt",
    "content": "# this is used by render to install dependencies\n-r ./pyproject.txt\nsrc/python-fastui\nuvicorn[standard]\nhttpx\nPyJWT\n"
  },
  {
    "path": "src/python-fastui/requirements/test.in",
    "content": "coverage\npytest\npytest-pretty\ndirty-equals\npytest-asyncio\nhttpx\nPyJWT\n"
  },
  {
    "path": "src/python-fastui/requirements/test.txt",
    "content": "#\n# This file is autogenerated by pip-compile with Python 3.14\n# by the following command:\n#\n#    pip-compile --constraint=src/python-fastui/requirements/lint.txt --constraint=src/python-fastui/requirements/pyproject.txt --output-file=src/python-fastui/requirements/test.txt --strip-extras src/python-fastui/requirements/test.in\n#\nanyio==4.11.0\n    # via\n    #   -c src/python-fastui/requirements/pyproject.txt\n    #   httpx\ncertifi==2024.2.2\n    # via\n    #   httpcore\n    #   httpx\ncoverage==7.4.1\n    # via -r src/python-fastui/requirements/test.in\ndirty-equals==0.7.1.post0\n    # via -r src/python-fastui/requirements/test.in\nh11==0.14.0\n    # via httpcore\nhttpcore==1.0.8\n    # via httpx\nhttpx==0.28.1\n    # via -r src/python-fastui/requirements/test.in\nidna==3.11\n    # via\n    #   -c src/python-fastui/requirements/pyproject.txt\n    #   anyio\n    #   httpx\niniconfig==2.3.0\n    # via pytest\nmarkdown-it-py==3.0.0\n    # via rich\nmdurl==0.1.2\n    # via markdown-it-py\npackaging==25.0\n    # via pytest\npluggy==1.6.0\n    # via pytest\npygments==2.19.2\n    # via\n    #   pytest\n    #   rich\npyjwt==2.8.0\n    # via -r src/python-fastui/requirements/test.in\npytest==8.4.2\n    # via\n    #   -r src/python-fastui/requirements/test.in\n    #   pytest-asyncio\n    #   pytest-pretty\npytest-asyncio==1.2.0\n    # via -r src/python-fastui/requirements/test.in\npytest-pretty==1.3.0\n    # via -r src/python-fastui/requirements/test.in\npytz==2025.2\n    # via dirty-equals\nrich==14.2.0\n    # via pytest-pretty\nsniffio==1.3.1\n    # via\n    #   -c src/python-fastui/requirements/pyproject.txt\n    #   anyio\n"
  },
  {
    "path": "src/python-fastui/tests/test_auth_github.py",
    "content": "from datetime import datetime\n\nimport pytest\nfrom fastapi import FastAPI\nfrom fastui.auth import AuthError, GitHubAuthProvider, GitHubEmail\nfrom fastui.auth.github import EXCHANGE_CACHE\nfrom httpx import ASGITransport, AsyncClient\nfrom pydantic import SecretStr\n\n\n@pytest.fixture\ndef github_requests() -> list[str]:\n    return []\n\n\n@pytest.fixture\ndef fake_github_app(github_requests: list[str]) -> FastAPI:\n    app = FastAPI()\n\n    @app.post('/login/oauth/access_token')\n    async def access_token(code: str, client_id: str, client_secret: str, redirect_uri: str | None = None):\n        r = f'/login/oauth/access_token code={code}'\n        if redirect_uri:\n            r += f' redirect_uri={redirect_uri}'\n        github_requests.append(r)\n        assert client_id == '1234'\n        assert client_secret == 'secret'\n        if code == 'good_user':\n            return {'access_token': 'good_token_user', 'token_type': 'bearer', 'scope': 'user'}\n        elif code == 'good':\n            return {'access_token': 'good_token', 'token_type': 'bearer', 'scope': ''}\n        elif code == 'bad_expected':\n            return {'error': 'bad_verification_code'}\n        else:\n            return {'error': 'bad_code'}\n\n    @app.get('/user')\n    async def user():\n        github_requests.append('/user')\n        return {\n            'login': 'test_user',\n            'name': 'Test User',\n            'email': 'test@example.com',\n            'avatar_url': 'https://example.com/avatar.png',\n            'created_at': '2022-01-01T00:00:00Z',\n            'updated_at': '2022-01-01T00:00:00Z',\n            'public_repos': 0,\n            'public_gists': 0,\n            'followers': 0,\n            'following': 0,\n            'company': None,\n            'blog': None,\n            'location': None,\n            'hireable': None,\n            'bio': None,\n        }\n\n    @app.get('/user/emails')\n    async def user_emails():\n        github_requests.append('/user/emails')\n        return [\n            {'email': 'foo@example.com', 'primary': False, 'verified': True, 'visibility': None},\n            {'email': 'bar@example.com', 'primary': True, 'verified': True, 'visibility': 'public'},\n        ]\n\n    return app\n\n\n@pytest.fixture\nasync def httpx_client(fake_github_app: FastAPI):\n    transport = ASGITransport(app=fake_github_app)\n    async with AsyncClient(transport=transport, base_url='http://test') as client:\n        yield client\n\n\n@pytest.fixture\nasync def github_auth_provider(httpx_client: AsyncClient):\n    return GitHubAuthProvider(\n        httpx_client=httpx_client,\n        github_client_id='1234',\n        github_client_secret=SecretStr('secret'),\n        state_provider=False,\n        exchange_cache_age=None,\n    )\n\n\nasync def test_get_auth_url(github_auth_provider: GitHubAuthProvider):\n    url = await github_auth_provider.authorization_url()\n    # no state here\n    assert url == 'https://github.com/login/oauth/authorize?client_id=1234'\n\n\nasync def test_get_auth_url_scopes(httpx_client: AsyncClient):\n    provider = GitHubAuthProvider(\n        httpx_client=httpx_client,\n        github_client_id='1234',\n        github_client_secret=SecretStr('secret'),\n        scopes=['user:email', 'read:org'],\n        state_provider=False,\n        exchange_cache_age=None,\n    )\n    url = await provider.authorization_url()\n    # insert_assert(url)\n    assert url == 'https://github.com/login/oauth/authorize?client_id=1234&scope=user%3Aemail+read%3Aorg'\n\n\nasync def test_exchange_ok(github_auth_provider: GitHubAuthProvider, github_requests: list[str]):\n    assert github_requests == []\n    exchange = await github_auth_provider.exchange_code('good')\n    assert exchange.access_token == 'good_token'\n    assert exchange.token_type == 'bearer'\n    assert exchange.scope == []\n    assert github_requests == ['/login/oauth/access_token code=good']\n\n\nasync def test_exchange_ok_user(github_auth_provider: GitHubAuthProvider):\n    exchange = await github_auth_provider.exchange_code('good_user')\n    assert exchange.access_token == 'good_token_user'\n    assert exchange.token_type == 'bearer'\n    assert exchange.scope == ['user']\n\n\nasync def test_exchange_bad_expected(github_auth_provider: GitHubAuthProvider):\n    with pytest.raises(AuthError, match='^Invalid GitHub verification code'):\n        await github_auth_provider.exchange_code('bad_expected')\n\n\nasync def test_exchange_bad_unexpected(github_auth_provider: GitHubAuthProvider):\n    with pytest.raises(RuntimeError, match='^Unexpected response from GitHub access token exchange'):\n        await github_auth_provider.exchange_code('unknown')\n\n\n@pytest.fixture\nasync def github_auth_provider_state(fake_github_app: FastAPI, httpx_client: AsyncClient):\n    return GitHubAuthProvider(\n        httpx_client=httpx_client,\n        github_client_id='1234',\n        github_client_secret=SecretStr('secret'),\n        state_provider=True,\n    )\n\n\nasync def test_exchange_no_state(github_auth_provider_state: GitHubAuthProvider):\n    with pytest.raises(AuthError, match='^Missing GitHub auth state'):\n        await github_auth_provider_state.exchange_code('good')\n\n\nasync def test_exchange_bad_state(github_auth_provider_state: GitHubAuthProvider):\n    with pytest.raises(AuthError, match='^Invalid GitHub auth state'):\n        await github_auth_provider_state.exchange_code('good', 'bad_state')\n\n\nasync def test_exchange_good_state(github_auth_provider_state: GitHubAuthProvider):\n    url = await github_auth_provider_state.authorization_url()\n    assert url.startswith('https://github.com/login/oauth/authorize?client_id=1234&state=')\n    state = url.rsplit('=', 1)[-1]\n\n    exchange = await github_auth_provider_state.exchange_code('good', state)\n    assert exchange.access_token == 'good_token'\n\n\nasync def test_exchange_bad_state_file_exists(github_auth_provider_state: GitHubAuthProvider):\n    url = await github_auth_provider_state.authorization_url()\n    assert url.startswith('https://github.com/login/oauth/authorize?client_id=1234&state=')\n\n    with pytest.raises(AuthError, match='^Invalid GitHub auth state'):\n        await github_auth_provider_state.exchange_code('good', 'bad_state')\n\n\nasync def test_exchange_ok_repeat(github_auth_provider: GitHubAuthProvider, github_requests: list[str]):\n    assert github_requests == []\n    exchange = await github_auth_provider.exchange_code('good')\n    assert exchange.access_token == 'good_token'\n    assert exchange.token_type == 'bearer'\n    assert exchange.scope == []\n    assert github_requests == ['/login/oauth/access_token code=good']\n\n    exchange = await github_auth_provider.exchange_code('good')\n    assert exchange.access_token == 'good_token'\n\n    assert github_requests == ['/login/oauth/access_token code=good', '/login/oauth/access_token code=good']\n\n\nasync def test_exchange_ok_repeat_cached(\n    fake_github_app: FastAPI, httpx_client: AsyncClient, github_requests: list[str]\n):\n    github_auth_provider = GitHubAuthProvider(\n        httpx_client=httpx_client,\n        github_client_id='1234',\n        github_client_secret=SecretStr('secret'),\n        state_provider=False,\n    )\n    EXCHANGE_CACHE.clear()\n    assert len(EXCHANGE_CACHE) == 0\n    assert github_requests == []\n    await github_auth_provider.exchange_code('good')\n    assert len(EXCHANGE_CACHE) == 1\n    assert github_requests == ['/login/oauth/access_token code=good']\n    await github_auth_provider.exchange_code('good')\n    assert github_requests == ['/login/oauth/access_token code=good']  # no repeat request to github\n    await github_auth_provider.exchange_code('good_user')\n    assert github_requests == ['/login/oauth/access_token code=good', '/login/oauth/access_token code=good_user']\n\n\nasync def test_exchange_cached_purge(fake_github_app: FastAPI, httpx_client: AsyncClient):\n    github_auth_provider = GitHubAuthProvider(\n        httpx_client=httpx_client,\n        github_client_id='1234',\n        github_client_secret=SecretStr('secret'),\n        state_provider=False,\n    )\n    EXCHANGE_CACHE.clear()\n    await github_auth_provider.exchange_code('good')\n    assert len(EXCHANGE_CACHE) == 1\n\n    # manually add an old entry\n    EXCHANGE_CACHE._data['old'] = (datetime(2020, 1, 1), 'old_token')\n    assert len(EXCHANGE_CACHE) == 2\n\n    await github_auth_provider.exchange_code('good')\n    assert len(EXCHANGE_CACHE) == 1\n\n\nasync def test_exchange_redirect_url(fake_github_app: FastAPI, httpx_client: AsyncClient, github_requests: list[str]):\n    github_auth_provider = GitHubAuthProvider(\n        httpx_client=httpx_client,\n        github_client_id='1234',\n        github_client_secret=SecretStr('secret'),\n        redirect_uri='/callback',\n        state_provider=False,\n        exchange_cache_age=None,\n    )\n    url = await github_auth_provider.authorization_url()\n    assert url == 'https://github.com/login/oauth/authorize?client_id=1234&redirect_uri=%2Fcallback'\n    exchange = await github_auth_provider.exchange_code('good')\n    assert exchange.access_token == 'good_token'\n    assert github_requests == ['/login/oauth/access_token code=good redirect_uri=/callback']\n\n\nasync def test_get_github_user(github_auth_provider: GitHubAuthProvider, github_requests: list[str]):\n    assert github_requests == []\n    exchange = await github_auth_provider.exchange_code('good')\n    assert github_requests == ['/login/oauth/access_token code=good']\n    user = await github_auth_provider.get_github_user(exchange)\n    assert user.login == 'test_user'\n    assert user.name == 'Test User'\n    assert user.email == 'test@example.com'\n\n    assert github_requests == ['/login/oauth/access_token code=good', '/user']\n\n\nasync def test_get_github_user_emails(github_auth_provider: GitHubAuthProvider, github_requests: list[str]):\n    assert github_requests == []\n    exchange = await github_auth_provider.exchange_code('good')\n    assert github_requests == ['/login/oauth/access_token code=good']\n    emails = await github_auth_provider.get_github_user_emails(exchange)\n    assert emails == [\n        GitHubEmail(email='foo@example.com', primary=False, verified=True, visibility=None),\n        GitHubEmail(email='bar@example.com', primary=True, verified=True, visibility='public'),\n    ]\n    assert github_requests == ['/login/oauth/access_token code=good', '/user/emails']\n\n\nasync def test_create():\n    async with GitHubAuthProvider.create('foo', SecretStr('bar')) as provider:\n        assert isinstance(provider._httpx_client, AsyncClient)\n"
  },
  {
    "path": "src/python-fastui/tests/test_auth_shared.py",
    "content": "import pytest\nfrom fastapi import FastAPI\nfrom fastui.auth import AuthError, AuthRedirect, fastapi_auth_exception_handling\nfrom starlette.testclient import TestClient\n\n\n@pytest.fixture(name='app')\ndef app_fixture() -> FastAPI:\n    app = FastAPI()\n    fastapi_auth_exception_handling(app)\n\n    @app.post('/do-redirect/')\n    async def do_redirect():\n        raise AuthRedirect('/new-path')\n\n    @app.post('/do-error/')\n    async def do_error():\n        raise AuthError('error message', code='error-code')\n\n    return app\n\n\n@pytest.fixture\ndef client(app: FastAPI):\n    with TestClient(app) as test_client:\n        yield test_client\n\n\ndef test_auth_redirect(client: TestClient):\n    r = client.post('/do-redirect/')\n    assert r.status_code == 345\n    # insert_assert(r.json())\n    assert r.json() == [{'event': {'url': '/new-path', 'type': 'go-to'}, 'type': 'FireEvent'}]\n\n\ndef test_auth_error(client: TestClient):\n    r = client.post('/do-error/')\n    assert r.status_code == 401\n    assert r.json() == {'detail': 'error message'}\n"
  },
  {
    "path": "src/python-fastui/tests/test_components.py",
    "content": "\"\"\"\nSimple tests of component creation.\n\nNOTE: we do NOT want to exhaustively construct every component just for the same of it -\nthat's just testing pydantic!\n\"\"\"\nfrom fastui import FastUI, components\nfrom pydantic import HttpUrl\n\n\ndef test_div_text():\n    div = components.Div(components=[components.Text(text='hello world')])\n\n    assert div.model_dump(by_alias=True, exclude_none=True) == {\n        'components': [\n            {\n                'text': 'hello world',\n                'type': 'Text',\n            },\n        ],\n        'type': 'Div',\n    }\n\n\ndef test_div_class_name():\n    div = components.Div(components=[], class_name='foobar')\n\n    assert div.model_dump(by_alias=True, exclude_none=True) == {\n        'components': [],\n        'className': 'foobar',\n        'type': 'Div',\n    }\n\n\ndef test_root_model():\n    m = FastUI(root=[components.Text(text='hello world')])\n    assert m.model_dump(by_alias=True, exclude_none=True) == [\n        {\n            'text': 'hello world',\n            'type': 'Text',\n        }\n    ]\n\n\ndef test_root_model_single():\n    # fixed by validator\n    m = FastUI(root=components.Text(text='hello world'))\n    assert m.model_dump(by_alias=True, exclude_none=True) == [\n        {\n            'text': 'hello world',\n            'type': 'Text',\n        }\n    ]\n\n\ndef test_iframe():\n    iframe = components.Iframe(src='https://www.example.com', srcdoc='<p>hello world</p>', sandbox='allow-scripts')\n    assert iframe.model_dump(by_alias=True, exclude_none=True) == {\n        'src': HttpUrl('https://www.example.com'),\n        'type': 'Iframe',\n        'srcdoc': '<p>hello world</p>',\n        'sandbox': 'allow-scripts',\n    }\n"
  },
  {
    "path": "src/python-fastui/tests/test_dev.py",
    "content": "from unittest.mock import patch\n\nfrom fastui.dev import dev_fastapi_app\nfrom httpx import ASGITransport, AsyncClient\n\n\ndef mock_signal(_sig, on_signal):\n    on_signal()\n\n\nasync def test_dev_connect():\n    with patch('fastui.dev.signal.signal', new=mock_signal):\n        app = dev_fastapi_app()\n        async with app.router.lifespan_context(app):\n            transport = ASGITransport(app=app)\n            async with AsyncClient(transport=transport, base_url='http://test') as client:\n                r = await client.get('/api/__dev__/reload')\n                assert r.status_code == 200\n                assert r.headers['content-type'] == 'text/plain; charset=utf-8'\n                assert r.text.startswith('fastui-dev-reload\\n')\n"
  },
  {
    "path": "src/python-fastui/tests/test_forms.py",
    "content": "import enum\nfrom contextlib import asynccontextmanager\nfrom io import BytesIO\nfrom typing import Annotated\n\nimport pytest\nfrom fastapi import HTTPException\nfrom fastui import components\nfrom fastui.forms import FormFile, Textarea, fastui_form\nfrom pydantic import BaseModel, Field\nfrom starlette.datastructures import FormData, Headers, UploadFile\n\n\nclass SimpleForm(BaseModel):\n    name: str\n    size: int = 4\n\n\nclass FakeRequest:\n    \"\"\"\n    TODO replace this with httpx or similar maybe, perhaps this is sufficient\n    \"\"\"\n\n    def __init__(self, form_data_list: list[tuple[str, str | UploadFile]]):\n        self._form_data = FormData(form_data_list)\n\n    @asynccontextmanager\n    async def form(self):\n        yield self._form_data\n\n\ndef test_simple_form_fields():\n    m = components.ModelForm(model=SimpleForm, submit_url='/foobar/')\n\n    assert m.model_dump(by_alias=True, exclude_none=True) == {\n        'submitUrl': '/foobar/',\n        'method': 'POST',\n        'type': 'ModelForm',\n        'formFields': [\n            {\n                'name': 'name',\n                'title': ['Name'],\n                'required': True,\n                'locked': False,\n                'htmlType': 'text',\n                'type': 'FormFieldInput',\n            },\n            {\n                'name': 'size',\n                'title': ['Size'],\n                'initial': 4,\n                'required': False,\n                'locked': False,\n                'htmlType': 'number',\n                'type': 'FormFieldInput',\n            },\n        ],\n    }\n\n\ndef test_inline_form_fields():\n    m = components.ModelForm(model=SimpleForm, submit_url='/foobar/', display_mode='inline')\n\n    assert m.model_dump(by_alias=True, exclude_none=True) == {\n        'submitUrl': '/foobar/',\n        'method': 'POST',\n        'type': 'ModelForm',\n        'displayMode': 'inline',\n        'footer': [],\n        'formFields': [\n            {\n                'name': 'name',\n                'title': ['Name'],\n                'required': True,\n                'locked': False,\n                'htmlType': 'text',\n                'type': 'FormFieldInput',\n            },\n            {\n                'name': 'size',\n                'title': ['Size'],\n                'initial': 4,\n                'required': False,\n                'locked': False,\n                'htmlType': 'number',\n                'type': 'FormFieldInput',\n            },\n        ],\n    }\n\n\nasync def test_simple_form_submit():\n    form_dep = fastui_form(SimpleForm)\n\n    request = FakeRequest([('name', 'bar'), ('size', '123')])\n\n    m = await form_dep.dependency(request)\n    assert isinstance(m, SimpleForm)\n    assert m.model_dump() == {'name': 'bar', 'size': 123}\n\n\nasync def test_simple_form_submit_repeat():\n    form_dep = fastui_form(SimpleForm)\n\n    request = FakeRequest([('name', 'bar'), ('size', '123'), ('size', '456')])\n\n    with pytest.raises(HTTPException) as exc_info:\n        await form_dep.dependency(request)\n\n    # insert_assert(exc_info.value.detail)\n    assert exc_info.value.detail == {\n        'form': [{'type': 'int_type', 'loc': ('size',), 'msg': 'Input should be a valid integer'}]\n    }\n\n\nclass FormWithNested(BaseModel):\n    name: str\n\n    class NestedForm(BaseModel):\n        x: int\n\n    nested: NestedForm\n\n\ndef test_w_nested_form_fields():\n    m = components.ModelForm(model=FormWithNested, submit_url='/foobar/')\n\n    # insert_assert(m.model_dump(by_alias=True, exclude_none=True))\n    assert m.model_dump(by_alias=True, exclude_none=True) == {\n        'submitUrl': '/foobar/',\n        'method': 'POST',\n        'type': 'ModelForm',\n        'formFields': [\n            {\n                'name': 'name',\n                'title': ['Name'],\n                'required': True,\n                'locked': False,\n                'htmlType': 'text',\n                'type': 'FormFieldInput',\n            },\n            {\n                'name': 'nested.x',\n                'title': ['NestedForm', 'X'],\n                'required': True,\n                'locked': False,\n                'htmlType': 'number',\n                'type': 'FormFieldInput',\n            },\n        ],\n    }\n\n\nasync def test_w_nested_form_submit():\n    form_dep = fastui_form(FormWithNested)\n\n    request = FakeRequest([('name', 'bar'), ('nested.x', '123')])\n\n    m = await form_dep.dependency(request)\n    assert isinstance(m, FormWithNested)\n    assert m.model_dump() == {'name': 'bar', 'nested': {'x': 123}}\n\n\nclass FormWithFile(BaseModel):\n    profile_pic: Annotated[UploadFile, FormFile()]\n\n\ndef test_file():\n    m = components.ModelForm(model=FormWithFile, submit_url='/foobar/')\n\n    # insert_assert(m.model_dump(by_alias=True, exclude_none=True))\n    assert m.model_dump(by_alias=True, exclude_none=True) == {\n        'submitUrl': '/foobar/',\n        'method': 'POST',\n        'type': 'ModelForm',\n        'formFields': [\n            {\n                'name': 'profile_pic',\n                'title': ['Profile Pic'],\n                'required': True,\n                'locked': False,\n                'multiple': False,\n                'type': 'FormFieldFile',\n            }\n        ],\n    }\n\n\nasync def test_file_submit():\n    file = UploadFile(BytesIO(b'foobar'), size=6, filename='testing.txt')\n    request = FakeRequest([('profile_pic', file)])\n\n    m = await fastui_form(FormWithFile).dependency(request)\n    assert m.model_dump() == {'profile_pic': file}\n\n\nasync def test_file_submit_repeat():\n    file1 = UploadFile(BytesIO(b'foobar'), size=6, filename='testing1.txt')\n    file2 = UploadFile(BytesIO(b'foobar'), size=6, filename='testing2.txt')\n    request = FakeRequest([('profile_pic', file1), ('profile_pic', file2)])\n\n    with pytest.raises(HTTPException) as exc_info:\n        await fastui_form(FormWithFile).dependency(request)\n\n    # insert_assert(exc_info.value.detail)\n    assert exc_info.value.detail == {\n        'form': [{'type': 'not_file', 'loc': ('profile_pic',), 'msg': 'Input is not a file'}]\n    }\n\n\nclass FormWithFileConstraint(BaseModel):\n    profile_pic: Annotated[UploadFile, FormFile(accept='image/*', max_size=16_000)]\n\n\ndef test_file_constrained():\n    m = components.ModelForm(model=FormWithFileConstraint, submit_url='/foobar/')\n\n    # insert_assert(m.model_dump(by_alias=True, exclude_none=True))\n    assert m.model_dump(by_alias=True, exclude_none=True) == {\n        'submitUrl': '/foobar/',\n        'method': 'POST',\n        'type': 'ModelForm',\n        'formFields': [\n            {\n                'name': 'profile_pic',\n                'title': ['Profile Pic'],\n                'required': True,\n                'locked': False,\n                'multiple': False,\n                'accept': 'image/*',\n                'type': 'FormFieldFile',\n            }\n        ],\n    }\n\n\nasync def test_file_constrained_submit():\n    headers = Headers({'content-type': 'image/png'})\n    file = UploadFile(BytesIO(b'foobar'), size=16_000, headers=headers)\n    request = FakeRequest([('profile_pic', file)])\n\n    m = await fastui_form(FormWithFileConstraint).dependency(request)\n    assert m.model_dump() == {'profile_pic': file}\n\n\nasync def test_file_constrained_submit_filename():\n    file = UploadFile(BytesIO(b'foobar'), size=16_000, filename='image.png')\n    request = FakeRequest([('profile_pic', file)])\n\n    m = await fastui_form(FormWithFileConstraint).dependency(request)\n    assert m.model_dump() == {'profile_pic': file}\n\n\nasync def test_file_constrained_submit_too_big():\n    headers = Headers({'content-type': 'image/png'})\n    file = UploadFile(BytesIO(b'foobar'), size=16_001, filename='image.png', headers=headers)\n    request = FakeRequest([('profile_pic', file)])\n\n    with pytest.raises(HTTPException) as exc_info:\n        await fastui_form(FormWithFileConstraint).dependency(request)\n\n    # insert_assert(exc_info.value.detail)\n    assert exc_info.value.detail == {\n        'form': [\n            {\n                'type': 'file_too_big',\n                'loc': ('profile_pic',),\n                'msg': 'File size was 15.6KiB, exceeding maximum allowed size of 15.6KiB',\n            }\n        ]\n    }\n\n\nasync def test_file_constrained_submit_wrong_type():\n    headers = Headers({'content-type': 'text/plain'})\n    file = UploadFile(BytesIO(b'foobar'), size=16, filename='testing.txt', headers=headers)\n    request = FakeRequest([('profile_pic', file)])\n\n    with pytest.raises(HTTPException) as exc_info:\n        await fastui_form(FormWithFileConstraint).dependency(request)\n\n    # insert_assert(exc_info.value.detail)\n    assert exc_info.value.detail == {\n        'form': [\n            {\n                'type': 'accept_mismatch',\n                'loc': ('profile_pic',),\n                'msg': (\n                    'Uploaded file \"testing.txt\" with content type \"text/plain\" '\n                    'does not match accept criteria \"image/*\"'\n                ),\n            }\n        ]\n    }\n\n\nclass FormMultipleFiles(BaseModel):\n    files: Annotated[list[UploadFile], FormFile()]\n\n\ndef test_multiple_files():\n    m = components.ModelForm(model=FormMultipleFiles, submit_url='/foobar/')\n\n    # insert_assert(m.model_dump(by_alias=True, exclude_none=True))\n    assert m.model_dump(by_alias=True, exclude_none=True) == {\n        'submitUrl': '/foobar/',\n        'method': 'POST',\n        'type': 'ModelForm',\n        'formFields': [\n            {\n                'name': 'files',\n                'title': ['Files'],\n                'required': True,\n                'locked': False,\n                'multiple': True,\n                'type': 'FormFieldFile',\n            }\n        ],\n    }\n\n\nasync def test_multiple_files_single():\n    file = UploadFile(BytesIO(b'foobar'), size=16_000, filename='image.png')\n    request = FakeRequest([('files', file)])\n\n    m = await fastui_form(FormMultipleFiles).dependency(request)\n    assert m.model_dump() == {'files': [file]}\n\n\nasync def test_multiple_files_multiple():\n    file1 = UploadFile(BytesIO(b'foobar'), size=6, filename='image1.png')\n    file2 = UploadFile(BytesIO(b'foobar'), size=6, filename='image2.png')\n    request = FakeRequest([('files', file1), ('files', file2)])\n\n    m = await fastui_form(FormMultipleFiles).dependency(request)\n    assert m.model_dump() == {'files': [file1, file2]}\n\n\nclass FixedTuple(BaseModel):\n    foo: tuple[str, int, int]\n\n\ndef test_fixed_tuple():\n    m = components.ModelForm(model=FixedTuple, submit_url='/foo/')\n    # insert_assert(m.model_dump(by_alias=True, exclude_none=True))\n    assert m.model_dump(by_alias=True, exclude_none=True) == {\n        'submitUrl': '/foo/',\n        'method': 'POST',\n        'type': 'ModelForm',\n        'formFields': [\n            {\n                'name': 'foo.0',\n                'title': ['Foo', '0'],\n                'required': True,\n                'locked': False,\n                'htmlType': 'text',\n                'type': 'FormFieldInput',\n            },\n            {\n                'name': 'foo.1',\n                'title': ['Foo', '1'],\n                'required': True,\n                'locked': False,\n                'htmlType': 'number',\n                'type': 'FormFieldInput',\n            },\n            {\n                'name': 'foo.2',\n                'title': ['Foo', '2'],\n                'required': True,\n                'locked': False,\n                'htmlType': 'number',\n                'type': 'FormFieldInput',\n            },\n        ],\n    }\n\n\nasync def test_fixed_tuple_submit():\n    request = FakeRequest([('foo.0', 'bar'), ('foo.1', '123'), ('foo.2', '456')])\n\n    m = await fastui_form(FixedTuple).dependency(request)\n    assert m.model_dump() == {'foo': ('bar', 123, 456)}\n\n\nclass NestedTuple(BaseModel):\n    bar: FixedTuple\n\n\ndef test_fixed_tuple_nested():\n    m = components.ModelForm(model=NestedTuple, submit_url='/foobar/')\n    # insert_assert(m.model_dump(by_alias=True, exclude_none=True))\n    assert m.model_dump(by_alias=True, exclude_none=True) == {\n        'submitUrl': '/foobar/',\n        'method': 'POST',\n        'type': 'ModelForm',\n        'formFields': [\n            {\n                'name': 'bar.foo.0',\n                'title': ['FixedTuple', 'Foo', '0'],\n                'required': True,\n                'locked': False,\n                'htmlType': 'text',\n                'type': 'FormFieldInput',\n            },\n            {\n                'name': 'bar.foo.1',\n                'title': ['FixedTuple', 'Foo', '1'],\n                'required': True,\n                'locked': False,\n                'htmlType': 'number',\n                'type': 'FormFieldInput',\n            },\n            {\n                'name': 'bar.foo.2',\n                'title': ['FixedTuple', 'Foo', '2'],\n                'required': True,\n                'locked': False,\n                'htmlType': 'number',\n                'type': 'FormFieldInput',\n            },\n        ],\n    }\n\n\nasync def test_fixed_tuple_nested_submit():\n    request = FakeRequest([('bar.foo.0', 'bar'), ('bar.foo.1', '123'), ('bar.foo.2', '456')])\n\n    m = await fastui_form(NestedTuple).dependency(request)\n    assert m.model_dump() == {'bar': {'foo': ('bar', 123, 456)}}\n\n\ndef test_variable_tuple():\n    class VarTuple(BaseModel):\n        foo: tuple[str, ...]\n\n    m = components.ModelForm(model=VarTuple, submit_url='/foo/')\n    with pytest.raises(NotImplementedError, match='Array fields are not fully supported'):\n        m.model_dump(by_alias=True, exclude_none=True)\n\n\ndef test_tuple_optional():\n    class TupleOptional(BaseModel):\n        foo: tuple[str, str | None]\n\n    m = components.ModelForm(model=TupleOptional, submit_url='/foo/')\n    with pytest.raises(NotImplementedError, match='Tuples with optional fields are not yet supported'):\n        m.model_dump(by_alias=True, exclude_none=True)\n\n\nclass FormTextarea(BaseModel):\n    text: Annotated[str, Textarea()]\n\n\ndef test_form_textarea_form_fields():\n    m = components.ModelForm(model=FormTextarea, submit_url='/foobar/')\n\n    assert m.model_dump(by_alias=True, exclude_none=True) == {\n        'submitUrl': '/foobar/',\n        'method': 'POST',\n        'type': 'ModelForm',\n        'formFields': [\n            {\n                'name': 'text',\n                'title': ['Text'],\n                'required': True,\n                'locked': False,\n                'type': 'FormFieldTextarea',\n            }\n        ],\n    }\n\n\nclass SelectEnum(str, enum.Enum):\n    one = 'one'\n    two = 'two'\n\n\nclass FormSelectMultiple(BaseModel):\n    select_single: SelectEnum = Field(title='Select Single', description='first field')\n    select_single_2: SelectEnum = Field(title='Select Single')  # unset description to test leakage from prev. field\n    select_multiple: list[SelectEnum] = Field(title='Select Multiple', description='third field')\n\n\ndef test_form_description_leakage():\n    m = components.ModelForm(model=FormSelectMultiple, submit_url='/foobar/')\n    assert m.model_dump(by_alias=True, exclude_none=True) == {\n        'formFields': [\n            {\n                'description': 'first field',\n                'locked': False,\n                'multiple': False,\n                'name': 'select_single',\n                'options': [{'label': 'One', 'value': 'one'}, {'label': 'Two', 'value': 'two'}],\n                'required': True,\n                'title': ['Select Single'],\n                'type': 'FormFieldSelect',\n            },\n            {\n                'locked': False,\n                'multiple': False,\n                'name': 'select_single_2',\n                'options': [{'label': 'One', 'value': 'one'}, {'label': 'Two', 'value': 'two'}],\n                'required': True,\n                'title': ['Select Single'],\n                'type': 'FormFieldSelect',\n            },\n            {\n                'description': 'third field',\n                'locked': False,\n                'multiple': True,\n                'name': 'select_multiple',\n                'options': [{'label': 'One', 'value': 'one'}, {'label': 'Two', 'value': 'two'}],\n                'required': True,\n                'title': ['Select Multiple'],\n                'type': 'FormFieldSelect',\n            },\n        ],\n        'method': 'POST',\n        'submitUrl': '/foobar/',\n        'type': 'ModelForm',\n    }\n\n\nclass RichForm(BaseModel):\n    repo: str = Field(json_schema_extra={'placeholder': '{org}/{repo}'}, title='GitHub repository')\n\n\ndef test_form_fields():\n    m = components.ModelForm(model=RichForm, submit_url='/foobar/')\n\n    assert m.model_dump(by_alias=True, exclude_none=True) == {\n        'formFields': [\n            {\n                'htmlType': 'text',\n                'locked': False,\n                'name': 'repo',\n                'placeholder': '{org}/{repo}',\n                'required': True,\n                'title': ['GitHub repository'],\n                'type': 'FormFieldInput',\n            }\n        ],\n        'method': 'POST',\n        'submitUrl': '/foobar/',\n        'type': 'ModelForm',\n    }\n"
  },
  {
    "path": "src/python-fastui/tests/test_json_schema.py",
    "content": "from dirty_equals import IsPartialDict\nfrom fastapi import FastAPI\nfrom fastui import FastUI, components\nfrom fastui.generate_typescript import generate_json_schema\nfrom httpx import ASGITransport, AsyncClient\n\n\nasync def test_json_schema():\n    schema = generate_json_schema(FastUI)\n    assert schema == {\n        '$defs': IsPartialDict({'AnyEvent': IsPartialDict()}),\n        'items': {'$ref': '#/$defs/FastProps'},\n        'title': 'FastUI',\n        'type': 'array',\n    }\n    # TODO test more specific cases\n\n\nasync def test_openapi():\n    app = FastAPI()\n\n    @app.get('/api/', response_model=FastUI, response_model_exclude_none=True)\n    def test_endpoint():\n        return [components.Text(text='hello')]\n\n    transport = ASGITransport(app=app)\n\n    async with AsyncClient(transport=transport, base_url='http://test') as client:\n        r = await client.get('/openapi.json')\n        assert r.status_code == 200\n        assert r.headers['content-type'] == 'application/json'\n        assert r.json() == {\n            'openapi': '3.1.0',\n            'info': {\n                'title': 'FastAPI',\n                'version': '0.1.0',\n            },\n            'paths': IsPartialDict(),\n            'components': IsPartialDict(),\n        }\n"
  },
  {
    "path": "src/python-fastui/tests/test_prebuilt_html.py",
    "content": "from fastui import prebuilt_html\n\n\ndef test_prebuilt_html():\n    html = prebuilt_html()\n    assert html.startswith('<!doctype html>')\n    assert 'https://cdn.jsdelivr.net/npm/@pydantic/fastui-prebuilt' in html\n    assert '<title></title>' in html\n    assert '<meta name=\"fastui:APIRootUrl\"' not in html\n    assert '<meta name=\"fastui:APIPathMode\"' not in html\n    assert '<meta name=\"fastui:APIPathStrip\"' not in html\n\n\ndef test_prebuilt_html_meta_tags():\n    html = prebuilt_html(\n        title='Test Title',\n        api_root_url='/admin/api',\n        api_path_mode='query',\n        api_path_strip='/admin',\n    )\n    assert '<title>Test Title</title>' in html\n    assert '<meta name=\"fastui:APIRootUrl\" content=\"/admin/api\" />' in html\n    assert '<meta name=\"fastui:APIPathMode\" content=\"query\" />' in html\n    assert '<meta name=\"fastui:APIPathStrip\" content=\"/admin\" />' in html\n"
  },
  {
    "path": "src/python-fastui/tests/test_tables_display.py",
    "content": "import pytest\nfrom fastui import components\nfrom fastui.components import display\nfrom pydantic import BaseModel, Field, computed_field\n\n\nclass User(BaseModel):\n    id: int\n    name: str = Field(title='Name')\n\n    @computed_field(title='Representation')\n    @property\n    def representation(self) -> str:\n        return f'{self.id}: {self.name}'\n\n\nusers = [User(id=1, name='john'), User(id=2, name='jack')]\n\n\ndef test_table_no_columns():\n    table = components.Table(data=users)\n\n    # insert_assert(table.model_dump(by_alias=True, exclude_none=True))\n    assert table.model_dump(by_alias=True, exclude_none=True) == {\n        'data': [\n            {'id': 1, 'name': 'john', 'representation': '1: john'},\n            {'id': 2, 'name': 'jack', 'representation': '2: jack'},\n        ],\n        'columns': [\n            {'field': 'id'},\n            {'field': 'name', 'title': 'Name'},\n            {'field': 'representation', 'title': 'Representation'},\n        ],\n        'type': 'Table',\n    }\n\n\ndef test_table_columns():\n    table = components.Table(\n        data=users,\n        columns=[\n            display.DisplayLookup(field='id', title='ID'),\n            display.DisplayLookup(field='name'),\n            display.DisplayLookup(field='representation'),\n        ],\n    )\n\n    # insert_assert(table.model_dump(by_alias=True, exclude_none=True))\n    assert table.model_dump(by_alias=True, exclude_none=True) == {\n        'data': [\n            {'id': 1, 'name': 'john', 'representation': '1: john'},\n            {'id': 2, 'name': 'jack', 'representation': '2: jack'},\n        ],\n        'columns': [\n            {'title': 'ID', 'field': 'id'},\n            {'title': 'Name', 'field': 'name'},\n            {'title': 'Representation', 'field': 'representation'},\n        ],\n        'type': 'Table',\n    }\n\n\ndef test_table_empty_no_data_model():\n    with pytest.raises(ValueError, match='Value error, Cannot infer model from empty data'):\n        components.Table(data=[])\n\n\ndef test_table_empty_data_model():\n    table = components.Table(data=[], data_model=User)\n\n    # insert_assert(table.model_dump(by_alias=True, exclude_none=True))\n    assert table.model_dump(by_alias=True, exclude_none=True) == {\n        'data': [],\n        'columns': [\n            {'field': 'id'},\n            {'title': 'Name', 'field': 'name'},\n            {'title': 'Representation', 'field': 'representation'},\n        ],\n        'type': 'Table',\n    }\n\n\ndef test_display_no_fields():\n    d = components.Details(data=users[0])\n\n    # insert_assert(d.model_dump(by_alias=True, exclude_none=True))\n    assert d.model_dump(by_alias=True, exclude_none=True) == {\n        'data': {'id': 1, 'name': 'john', 'representation': '1: john'},\n        'fields': [\n            {'field': 'id'},\n            {'title': 'Name', 'field': 'name'},\n            {'title': 'Representation', 'field': 'representation'},\n        ],\n        'type': 'Details',\n    }\n\n\ndef test_display_fields():\n    d = components.Details(\n        data=users[0], fields=[display.DisplayLookup(field='id', title='ID'), display.DisplayLookup(field='name')]\n    )\n\n    # insert_assert(d.model_dump(by_alias=True, exclude_none=True))\n    assert d.model_dump(by_alias=True, exclude_none=True) == {\n        'data': {'id': 1, 'name': 'john', 'representation': '1: john'},\n        'fields': [{'title': 'ID', 'field': 'id'}, {'title': 'Name', 'field': 'name'}],\n        'type': 'Details',\n    }\n\n\ndef test_details_with_display_lookup_and_display():\n    d = components.Details(\n        data=users[0],\n        fields=[\n            display.DisplayLookup(field='id', title='ID'),\n            display.DisplayLookup(field='name'),\n            display.Display(value='display value', title='Display Title'),\n        ],\n    )\n\n    # insert_assert(d.model_dump(by_alias=True, exclude_none=True))\n    assert d.model_dump(by_alias=True, exclude_none=True) == {\n        'data': {'id': 1, 'name': 'john', 'representation': '1: john'},\n        'fields': [\n            {'title': 'ID', 'field': 'id'},\n            {'title': 'Name', 'field': 'name'},\n            {'title': 'Display Title', 'value': 'display value', 'type': 'Display'},\n        ],\n        'type': 'Details',\n    }\n\n\ndef test_table_respect_computed_field_title():\n    class Foo(BaseModel):\n        id: int\n\n        @computed_field(title='Foo Name')\n        def name(self) -> str:\n            return f'foo{self.id}'\n\n    foos = [Foo(id=1)]\n    table = components.Table(data=foos)\n\n    # insert_assert(table.model_dump(by_alias=True, exclude_none=True))\n    assert table.model_dump(by_alias=True, exclude_none=True) == {\n        'data': [{'id': 1, 'name': 'foo1'}],\n        'columns': [{'field': 'id'}, {'title': 'Foo Name', 'field': 'name'}],\n        'type': 'Table',\n    }\n\n\ndef test_details_respect_computed_field_title():\n    class Foo(BaseModel):\n        id: int\n\n        @computed_field(title='Foo Name')\n        def name(self) -> str:\n            return f'foo{self.id}'\n\n    foos = Foo(id=1)\n    details = components.Details(data=foos)\n\n    # insert_assert(table.model_dump(by_alias=True, exclude_none=True))\n    assert details.model_dump(by_alias=True, exclude_none=True) == {\n        'data': {'id': 1, 'name': 'foo1'},\n        'fields': [{'field': 'id'}, {'title': 'Foo Name', 'field': 'name'}],\n        'type': 'Details',\n    }\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": false,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedIndexedAccess\": true,\n\n    /* Output */\n    \"declaration\": true\n  }\n}\n"
  },
  {
    "path": "typedoc.base.json",
    "content": "{\n  \"$schema\": \"https://typedoc.org/schema.json\",\n  \"includeVersion\": true\n}\n"
  },
  {
    "path": "typedoc.json",
    "content": "{\n  \"extends\": [\"./typedoc.base.json\"],\n  \"entryPointStrategy\": \"packages\",\n  \"entryPoints\": [\"./src/*\"]\n}\n"
  }
]