{
  "result": {
    "3.1.4": {
      "name": "ijson",
      "version": "3.1.4",
      "metadata_version": "2.1",
      "summary": "Iterative JSON parser with standard Python iterator interfaces",
      "home_page": "https://github.com/ICRAR/ijson",
      "author": "Rodrigo Tobar, Ivan Sagalaev",
      "author_email": "rtobar@icrar.org, maniac@softwaremaniacs.org",
      "maintainer": "",
      "maintainer_email": "",
      "license": "BSD",
      "description": ".. image:: https://travis-ci.com/ICRAR/ijson.svg?branch=master\n    :target: https://travis-ci.com/ICRAR/ijson\n\n.. image:: https://ci.appveyor.com/api/projects/status/32wiho6ojw3eakp8/branch/master?svg=true\n    :target: https://ci.appveyor.com/project/rtobar/ijson/branch/master\n\n.. image:: https://coveralls.io/repos/github/ICRAR/ijson/badge.svg?branch=master\n    :target: https://coveralls.io/github/ICRAR/ijson?branch=master\n\n.. image:: https://badge.fury.io/py/ijson.svg\n    :target: https://badge.fury.io/py/ijson\n\n.. image:: https://img.shields.io/pypi/pyversions/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dd/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dw/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dm/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n\n=====\nijson\n=====\n\nIjson is an iterative JSON parser with standard Python iterator interfaces.\n\n.. contents::\n   :local:\n\n\nInstallation\n============\n\nIjson is hosted in PyPI, so you should be able to install it via ``pip``::\n\n  pip install ijson\n\nBinary wheels are provided\nfor major platforms (Linux, MacOS, Windows)\nand python versions (2.7, 3.5+).\nThese are built and published automatically\nusing `cibuildwheel <https://cibuildwheel.readthedocs.io/en/stable/>`_\nvia Travis CI.\n\n\nUsage\n=====\n\nAll usage example will be using a JSON document describing geographical\nobjects:\n\n.. code-block:: json\n\n    {\n      \"earth\": {\n        \"europe\": [\n          {\"name\": \"Paris\", \"type\": \"city\", \"info\": { ... }},\n          {\"name\": \"Thames\", \"type\": \"river\", \"info\": { ... }},\n          // ...\n        ],\n        \"america\": [\n          {\"name\": \"Texas\", \"type\": \"state\", \"info\": { ... }},\n          // ...\n        ]\n      }\n    }\n\n\nHigh-level interfaces\n---------------------\n\nMost common usage is having ijson yield native Python objects out of a JSON\nstream located under a prefix.\nThis is done using the ``items`` function.\nHere's how to process all European cities:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    objects = ijson.items(f, 'earth.europe.item')\n    cities = (o for o in objects if o['type'] == 'city')\n    for city in cities:\n        do_something_with(city)\n\nFor how to build a prefix see the prefix_ section below.\n\nOther times it might be useful to iterate over object members\nrather than objects themselves (e.g., when objects are too big).\nIn that case one can use the ``kvitems`` function instead:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    european_places = ijson.kvitems(f, 'earth.europe.item')\n    names = (v for k, v in european_places if k == 'name')\n    for name in names:\n        do_something_with(name)\n\n\nLower-level interfaces\n----------------------\n\nSometimes when dealing with a particularly large JSON payload it may worth to\nnot even construct individual Python objects and react on individual events\nimmediately producing some result.\nThis is achieved using the ``parse`` function:\n\n.. code-block::  python\n\n    import ijson\n\n    parser = ijson.parse(urlopen('http://.../'))\n    stream.write('<geo>')\n    for prefix, event, value in parser:\n        if (prefix, event) == ('earth', 'map_key'):\n            stream.write('<%s>' % value)\n            continent = value\n        elif prefix.endswith('.name'):\n            stream.write('<object name=\"%s\"/>' % value)\n        elif (prefix, event) == ('earth.%s' % continent, 'end_map'):\n            stream.write('</%s>' % continent)\n    stream.write('</geo>')\n\nEven more bare-bones is the ability to react on individual events\nwithout even calculating a prefix\nusing the ``basic_parse`` function:\n\n.. code-block:: python\n\n    import ijson\n\n    events = ijson.basic_parse(urlopen('http://.../'))\n    num_names = sum(1 for event, value in events\n                    if event == 'map_key' and value == 'name')\n\n\n``bytes``/``str`` support\n-------------------------\n\nAlthough not usually how they are meant to be run,\nall the functions above also accept\n``bytes`` and ``str`` objects (and ``unicode`` in python 2.7)\ndirectly as inputs.\nThese are then internally wrapped into a file object,\nand further processed.\nThis is useful for testing and prototyping,\nbut probably not extremely useful in real-life scenarios.\n\n\n``asyncio`` support\n-------------------\n\nIn python 3.5+ all of the methods above\nwork also on file-like asynchronous objects,\nso they can be iterated asynchronously.\nIn other words, something like this:\n\n.. code-block:: python\n\n   import asyncio\n   import ijson\n\n   async def run():\n      f = await async_urlopen('http://..../')\n      async for object in ijson.items(f, 'earth.europe.item'):\n         if object['type'] == 'city':\n            do_something_with(city)\n   asyncio.run(run())\n\nAn explicit set of ``*_async`` functions also exists\noffering the same functionality,\nexcept they will fail if anything other\nthan a file-like asynchronous object is given to them.\n(so the example above can also be written using ``ijson.items_async``).\nIn fact in ijson version 3.0\nthis was the only way to access\nthe ``asyncio`` support.\n\n\nIntercepting events\n-------------------\n\nThe four routines shown above\ninternally chain against each other:\ntuples generated by ``basic_parse``\nare the input for ``parse``,\nwhose results are the input to ``kvitems`` and ``items``.\n\nNormally users don't see this interaction,\nas they only care about the final output\nof the function they invoked,\nbut there are occasions when tapping\ninto this invocation chain this could be handy.\nThis is supported\nby passing the output of one function\n(i.e., an iterable of events, usually a generator)\nas the input of another,\nopening the door for user event filtering or injection.\n\nFor instance if one wants to skip some content\nbefore full item parsing:\n\n.. code-block:: python\n\n  import io\n  import ijson\n\n  parse_events = ijson.parse(io.BytesIO(b'[\"skip\", {\"a\": 1}, {\"b\": 2}, {\"c\": 3}]'))\n  while True:\n      prefix, event, value = next(parse_event)\n      if value == \"skip\":\n          break\n  for obj in ijson.items(parse_events, 'item')\n      print(obj)\n\n\nNote that this interception\nonly makes sense for the ``basic_parse -> parse``,\n``parse -> items`` and ``parse -> kvitems`` interactions.\n\n\nPush interfaces\n---------------\n\nAll examples above use a file-like object as the data input\n(both the normal case, and for ``asyncio`` support),\nand hence are \"pull\" interfaces,\nwith the library reading data as necessary.\nIf for whatever reason it's not possible to use such method,\nyou can still **push** data\nthrough yet a different interface: `coroutines <https://www.python.org/dev/peps/pep-0342/>`_\n(via generators, not ``asyncio`` coroutines).\nCoroutines effectively allow users\nto send data to them at any point in time,\nwith a final *target* coroutine-like object\nreceiving the results.\n\nIn the following example\nthe user is doing the reading\ninstead of letting the library do it:\n\n.. code-block:: python\n\n   import ijson\n\n   @ijson.coroutine\n   def print_cities():\n      while True:\n         obj = (yield)\n         if obj['type'] != 'city':\n            continue\n         print(obj)\n\n   coro = ijson.items_coro(print_cities(), 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n   coro.close()\n\nAll four ijson iterators\nhave a ``*_coro`` counterpart\nthat work by pushing data into them.\nInstead of receiving a file-like object\nand option buffer size as arguments,\nthey receive a single ``target`` argument,\nwhich should be a coroutine-like object\n(anything implementing a ``send`` method)\nthrough which results will be published.\n\nAn alternative to providing a coroutine\nis to use ``ijson.sendable_list`` to accumulate results,\nproviding the list is cleared after each parsing iteration,\nlike this:\n\n.. code-block:: python\n\n   import ijson\n\n   events = ijson.sendable_list()\n   coro = ijson.items_coro(events, 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n      process_accumulated_events(events)\n      del events[:]\n   coro.close()\n   process_accumulated_events(events)\n\n\n.. _options:\n\nOptions\n=======\n\nAdditional options are supported by **all** ijson functions\nto give users more fine-grained control over certain operations:\n\n- The ``use_float`` option (defaults to ``False``)\n  controls how non-integer values are returned to the user.\n  If set to ``True`` users receive ``float()`` values;\n  otherwise ``Decimal`` values are constructed.\n  Note that building ``float`` values is usually faster,\n  but on the other hand there might be loss of precision\n  (which most applications will not care about)\n  and will raise an exception when overflow occurs\n  (e.g., if ``1e400`` is encountered).\n  This option also has the side-effect\n  that integer numbers bigger than ``2^64``\n  (but *sometimes* ``2^32``, see backends_)\n  will also raise an overflow error,\n  due to similar reasons.\n  Future versions of ijson\n  might change the default value of this option\n  to ``True``.\n- The ``multiple_values`` option (defaults to ``False``)\n  controls whether multiple top-level values are supported.\n  JSON content should contain a single top-level value\n  (see `the JSON Grammar <https://tools.ietf.org/html/rfc7159#section-2>`_).\n  However there are plenty of JSON files out in the wild\n  that contain multiple top-level values,\n  often separated by newlines.\n  By default ijson will fail to process these\n  with a ``parse error: trailing garbage`` error\n  unless ``multiple_values=True`` is specified.\n- Similarly the ``allow_comments`` option (defaults to ``False``)\n  controls whether C-style comments (e.g., ``/* a comment */``),\n  which are not supported by the JSON standard,\n  are allowed in the content or not.\n- For functions taking a file-like object,\n  an additional ``buf_size`` option (defaults to ``65536`` or 64KB)\n  specifies the amount of bytes the library\n  should attempt to read each time.\n- The ``items`` and ``kvitems`` functions, and all their variants,\n  have an optional ``map_type`` argument (defaults to ``dict``)\n  used to construct objects from the JSON stream.\n  This should be a dict-like type supporting item assignment.\n\n\nEvents\n======\n\nWhen using the lower-level ``ijson.parse`` function,\nthree-element tuples are generated\ncontaining a prefix, an event name, and a value.\nEvents will be one of the following:\n\n- ``start_map`` and ``end_map`` indicate\n  the beginning and end of a JSON object, respectively.\n  They carry a ``None`` as their value.\n- ``start_array`` and ``end_array`` indicate\n  the beginning and end of a JSON array, respectively.\n  They also carry a ``None`` as their value.\n- ``map_key`` indicates the name of a field in a JSON object.\n  Its associated value is the name itself.\n- ``null``, ``boolean``, ``integer``, ``double``, ``number`` and ``string``\n  all indicate actual content, which is stored in the associated value.\n\n\n.. _prefix:\n\nPrefix\n======\n\nA prefix represents the context within a JSON document\nwhere an event originates at.\nIt works as follows:\n\n- It starts as an empty string.\n- A ``<name>`` part is appended when the parser starts parsing the contents\n  of a JSON object member called ``name``,\n  and removed once the content finishes.\n- A literal ``item`` part is appended when the parser is parsing\n  elements of a JSON array,\n  and removed when the array ends.\n- Parts are separated by ``.``.\n\nWhen using the ``ijson.items`` function,\nthe prefix works as the selection\nfor which objects should be automatically built and returned by ijson.\n\n\n.. _backends:\n\nBackends\n========\n\nIjson provides several implementations of the actual parsing in the form of\nbackends located in ijson/backends:\n\n- ``yajl2_c``: a C extension using `YAJL <http://lloyd.github.com/yajl/>`_ 2.x.\n  This is the fastest, but *might* require a compiler and the YAJL development files\n  to be present when installing this package.\n  Binary wheel distributions exist for major platforms/architectures to spare users\n  from having to compile the package.\n- ``yajl2_cffi``: wrapper around `YAJL <http://lloyd.github.com/yajl/>`_ 2.x\n  using CFFI.\n- ``yajl2``: wrapper around YAJL 2.x using ctypes, for when you can't use CFFI\n  for some reason.\n- ``yajl``: deprecated YAJL 1.x + ctypes wrapper, for even older systems.\n- ``python``: pure Python parser, good to use with PyPy\n\nYou can import a specific backend and use it in the same way as the top level\nlibrary:\n\n.. code-block::  python\n\n    import ijson.backends.yajl2_cffi as ijson\n\n    for item in ijson.items(...):\n        # ...\n\nImporting the top level library as ``import ijson``\nuses the first available backend in the same order of the list above,\nand its name is recorded under ``ijson.backend``.\nIf the ``IJSON_BACKEND`` environment variable is set\nits value takes precedence and is used to select the default backend.\n\nYou can also use the ``ijson.get_backend`` function\nto get a specific backend based on a name:\n\n.. code-block:: python\n\n    backend = ijson.get_backend('yajl2_c')\n    for item in backend.items(...):\n        # ...\n\n\nPerformance tips\n================\n\nIn more-or-less decreasing order,\nthese are the most common actions you can take\nto ensure you get most of the performance\nout of ijson:\n\n- Make sure you use the fastest backend available.\n  See backends_ for details.\n- If you know your JSON data\n  contains only numbers that are \"well behaved\"\n  consider turning on the ``use_float`` option.\n  See options_ for details.\n- Make sure you feed ijson with binary data\n  instead of text data.\n  See faq_ #1 for details.\n- Play with the ``buf_size`` option,\n  as depending on your data source and your system\n  a value different from the default\n  might show better performance.\n  See options_ for details.\n\n\n.. _faq:\n\nFAQ\n===\n\n#. **Q**: Does ijson work with ``bytes`` or ``str`` values?\n\n   **A**: In short: both are accepted as input, outputs are only ``str``.\n\n   All ijson functions expecting a file-like object\n   should ideally be given one\n   that is opened in binary mode\n   (i.e., its ``read`` function returns ``bytes`` objects, not ``str``).\n   However if a text-mode file object is given\n   then the library will automatically\n   encode the strings into UTF-8 bytes.\n   A warning is currently issued (but not visible by default)\n   alerting users about this automatic conversion.\n\n   On the other hand ijson always returns text data\n   (JSON string values, object member names, event names, etc)\n   as ``str`` objects in python 3,\n   and ``unicode`` objects in python 2.7.\n   This mimics the behavior of the system ``json`` module.\n\n#. **Q**: How are numbers dealt with?\n\n   **A**: ijson returns ``int`` values for integers\n   and ``decimal.Decimal`` values for floating-point numbers.\n   This is mostly because of historical reasons.\n   Since 3.1 a new ``use_float`` option (defaults to ``False``)\n   is available to return ``float`` values instead.\n   See the options_ section for details.\n\n#. **Q**: I'm getting an ``UnicodeDecodeError``, or an ``IncompleteJSONError`` with no message\n\n   **A**: This error is caused by byte sequences that are not valid in UTF-8.\n   In other words, the data given to ijson is not *really* UTF-8 encoded,\n   or at least not properly.\n\n   Depending on where the data comes from you have different options:\n\n   * If you have control over the source of the data, fix it.\n\n   * If you have a way to intercept the data flow,\n     do so and pass it through a \"byte corrector\".\n     For instance, if you have a shell pipeline\n     feeding data through ``stdin`` into your process\n     you can add something like ``... | iconv -f utf8 -t utf8 -c | ...``\n     in between to correct invalid byte sequences.\n\n   * If you are working purely in python,\n     you can create a UTF-8 decoder\n     using codecs' `incrementaldecoder <https://docs.python.org/3/library/codecs.html#codecs.getincrementaldecoder>`_\n     to leniently decode your bytes into strings,\n     and feed those strings (using a file-like class) into ijson\n     (see our `string_reader_async internal class <https://github.com/ICRAR/ijson/blob/0157f3c65a7986970030d3faa75979ee205d3806/ijson/utils35.py#L19>`_\n     for some inspiration).\n\n   In the future ijson might offer something out of the box\n   to deal with invalid UTF-8 byte sequences.\n\n#. **Q**: I'm getting ``parse error: trailing garbage`` or ``Additional data found`` errors\n\n   **A**: This error signals that the input\n   contains more data than the top-level JSON value it's meant to contain.\n   This is *usually* caused by JSON data sources\n   containing multiple values, and is *usually* solved\n   by passing the ``multiple_values=True`` to the ijson function in use.\n   See the options_ section for details.\n\n#. **Q**: Are there any differences between the backends?\n\n   **A**: Apart from their performance,\n   all backends are designed to support the same capabilities.\n   There are however some small known differences:\n\n   * The ``yajl`` backend doesn't support ``multiple_values=True``.\n     It also doesn't complain about additional data\n     found after the end of the top-level JSON object.\n     When using ``use_float=True`` it also doesn't properly support\n     values greater than 2^32 in 32-bit platforms or Windows.\n     Numbers with leading zeros are not reported as invalid\n     (although they are invalid JSON numbers).\n     Incomplete JSON tokens at the end of an incomplete document\n     (e.g., ``{\"a\": fals``) are not reported as ``IncompleteJSONError``.\n\n   * The ``python`` backend doesn't support ``allow_comments=True``\n     It also internally works with ``str`` objects, not ``bytes``,\n     but this is an internal detail that users shouldn't need to worry about,\n     and might change in the future.\n\n\nAcknowledgements\n================\n\nijson was originally developed and actively maintained until 2016\nby `Ivan Sagalaev <http://softwaremaniacs.org/>`_.\nIn 2019 he\n`handed over <https://github.com/isagalaev/ijson/pull/58#issuecomment-500596815>`_\nthe maintenance of the project and the PyPI ownership.\n\nPython parser in ijson is relatively simple thanks to `Douglas Crockford\n<http://www.crockford.com/>`_ who invented a strict, easy to parse syntax.\n\nThe `YAJL <http://lloyd.github.com/yajl/>`_ library by `Lloyd Hilaiel\n<http://lloyd.io/>`_ is the most popular and efficient way to parse JSON in an\niterative fashion.\n\nIjson was inspired by `yajl-py <http://pykler.github.com/yajl-py/>`_ wrapper by\n`Hatem Nassrat <http://www.nassrat.ca/>`_. Though ijson borrows almost nothing\nfrom the actual yajl-py code it was used as an example of integration with yajl\nusing ctypes.\n",
      "keywords": "",
      "platform": [],
      "classifiers": [
        "Development Status :: 5 - Production/Stable",
        "License :: OSI Approved :: BSD License",
        "Programming Language :: Python :: 2.7",
        "Programming Language :: Python :: 3.4",
        "Programming Language :: Python :: 3.5",
        "Programming Language :: Python :: 3.6",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Environment :: MetaData :: IBM Python Ecosystem"
      ],
      "download_url": "",
      "supported_platform": [],
      "comment": "",
      "provides": [],
      "requires": [],
      "obsoletes": [],
      "project_urls": [],
      "provides_dist": [],
      "obsoletes_dist": [],
      "requires_dist": [],
      "requires_external": [],
      "requires_python": "",
      "description_content_type": "text/x-rst",
      "provides_extras": [],
      "dynamic": [],
      "license_expression": "",
      "license_file": [],
      "+links": [
        {
          "rel": "releasefile",
          "hash_spec": "sha256=fc1613e458de5c852736df4eeea41597f6915d4890cc81f3e635c32ec9bc574a",
          "hashes": {
            "sha256": "fc1613e458de5c852736df4eeea41597f6915d4890cc81f3e635c32ec9bc574a"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/fc1/613e458de5c85/ijson-3.1.4-py3-none-any.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                31
              ],
              "dst": "ppc64le/linux"
            }
          ]
        }
      ]
    },
    "3.4.0.post0": {
      "name": "ijson",
      "version": "3.4.0.post0",
      "metadata_version": "2.4",
      "summary": "Iterative JSON parser with standard Python iterator interfaces",
      "home_page": "",
      "author": "",
      "author_email": "Rodrigo Tobar <rtobar@icrar.org>, Ivan Sagalaev <maniac@softwaremaniacs.org>",
      "maintainer": "",
      "maintainer_email": "",
      "license": "",
      "description": ".. image:: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://github.com/ICRAR/ijson/actions/workflows/fast-built-and-test.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://coveralls.io/repos/github/ICRAR/ijson/badge.svg?branch=master\n    :target: https://coveralls.io/github/ICRAR/ijson?branch=master\n\n.. image:: https://badge.fury.io/py/ijson.svg\n    :target: https://badge.fury.io/py/ijson\n\n.. image:: https://img.shields.io/pypi/pyversions/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dd/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dw/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dm/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n\n=====\nijson\n=====\n\nIjson is an iterative JSON parser with standard Python iterator interfaces.\n\n.. contents::\n   :local:\n\n\nInstallation\n============\n\nIjson is hosted in PyPI, so you should be able to install it via ``pip``::\n\n  pip install ijson\n\nBinary wheels are provided\nfor major platforms\nand python versions.\nThese are built and published automatically\nusing `cibuildwheel <https://cibuildwheel.readthedocs.io/en/stable/>`_\nvia GitHub Actions.\n\n\nUsage\n=====\n\nAll usage example will be using a JSON document describing geographical\nobjects:\n\n.. code-block:: json\n\n    {\n      \"earth\": {\n        \"europe\": [\n          {\"name\": \"Paris\", \"type\": \"city\", \"info\": { ... }},\n          {\"name\": \"Thames\", \"type\": \"river\", \"info\": { ... }},\n          // ...\n        ],\n        \"america\": [\n          {\"name\": \"Texas\", \"type\": \"state\", \"info\": { ... }},\n          // ...\n        ]\n      }\n    }\n\n\nHigh-level interfaces\n---------------------\n\nijson works by continuously reading data from a JSON stream provided by the user.\nThis is presented as a file-like object.\nIn particular it must provide a ``read(size)`` method\nreturning either ``bytes`` (preferably) or ``str``.\nExample file-like objects are\nfiles opened with ``open``,\nHTTP/HTTPS requests made using ``urllib.request.urlopen``,\n``socket.socket`` objects,\nand more.\n\nThe most common usage of ijson is to yield native Python objects\nlocated under a prefix.\nThis is done using the ``items`` function.\nHere's how to process all European cities:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    objects = ijson.items(f, 'earth.europe.item')\n    cities = (o for o in objects if o['type'] == 'city')\n    for city in cities:\n        do_something_with(city)\n\nFor how to build a prefix see the prefix_ section below.\n\nOther times it might be useful to iterate over object members\nrather than objects themselves (e.g., when objects are too big).\nIn that case one can use the ``kvitems`` function instead:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    european_places = ijson.kvitems(f, 'earth.europe.item')\n    names = (v for k, v in european_places if k == 'name')\n    for name in names:\n        do_something_with(name)\n\n\nLower-level interfaces\n----------------------\n\nSometimes when dealing with a particularly large JSON payload it may worth to\nnot even construct individual Python objects and react on individual events\nimmediately producing some result.\nThis is achieved using the ``parse`` function:\n\n.. code-block::  python\n\n    import ijson\n\n    parser = ijson.parse(urlopen('http://.../'))\n    stream.write('<geo>')\n    for prefix, event, value in parser:\n        if (prefix, event) == ('earth', 'map_key'):\n            stream.write('<%s>' % value)\n            continent = value\n        elif prefix.endswith('.name'):\n            stream.write('<object name=\"%s\"/>' % value)\n        elif (prefix, event) == ('earth.%s' % continent, 'end_map'):\n            stream.write('</%s>' % continent)\n    stream.write('</geo>')\n\nEven more bare-bones is the ability to react on individual events\nwithout even calculating a prefix\nusing the ``basic_parse`` function:\n\n.. code-block:: python\n\n    import ijson\n\n    events = ijson.basic_parse(urlopen('http://.../'))\n    num_names = sum(1 for event, value in events\n                    if event == 'map_key' and value == 'name')\n\n\nCommand line\n------------\n\nA command line utility is included with ijson\nto help visualise the output of each of the routines above.\nIt reads JSON from the standard input,\nand it prints the results of the parsing method chosen by the user\nto the standard output.\n\nThe tool is available by running the ``ijson.dump`` module.\nFor example::\n\n $> echo '{\"A\": 0, \"B\": [1, 2, 3, 4]}' | python -m ijson.dump -m parse\n #: path, name, value\n --------------------\n 0: , start_map, None\n 1: , map_key, A\n 2: A, number, 0\n 3: , map_key, B\n 4: B, start_array, None\n 5: B.item, number, 1\n 6: B.item, number, 2\n 7: B.item, number, 3\n 8: B.item, number, 4\n 9: B, end_array, None\n 10: , end_map, None\n\nUsing ``-h/--help`` will show all available options.\n\n\nBenchmarking\n------------\n\nA command line utility is included with ijson\nto help benchmarking the different methods offered by the package.\nIt offers some built-in example inputs\nthat try to mimic different scenarios,\nbut more importantly it also supports user-provided inputs.\nYou can also specify which backends to time,\nnumber of iterations,\nand more.\n\nThe tool is available by running the ``ijson.benchmark`` module.\nFor example::\n\n $> python -m ijson.benchmark my/json/file.json -m items -p values.item\n\nUsing ``-h/--help`` will show all available options.\n\n\n``bytes``/``str`` support\n-------------------------\n\nAlthough not usually how they are meant to be run,\nall the functions above also accept\n``bytes`` and ``str`` objects\ndirectly as inputs.\nThese are then internally wrapped into a file object,\nand further processed.\nThis is useful for testing and prototyping,\nbut probably not extremely useful in real-life scenarios.\n\n\nIterator support\n----------------\n\nIn many situations the direct input users want to pass to ijson\nis an iterator (e.g., a generator) rather than a file-like object.\nTo bridge this gap users need to adapt the iterator into a file-like object.\nExamples of this can be found\n`here <https://github.com/ICRAR/ijson/issues/44#issuecomment-1771013830>`__\nand `here <https://github.com/ICRAR/ijson/issues/58#issuecomment-917655522>`__.\nFuture versions of ijson might provide built-in adapters for this,\nand/or support iterators without the need to adapt them first.\n\n\n``asyncio`` support\n-------------------\n\nAll of the methods above\nwork also on file-like asynchronous objects,\nso they can be iterated asynchronously.\nIn other words, something like this:\n\n.. code-block:: python\n\n   import asyncio\n   import ijson\n\n   async def run():\n      f = await async_urlopen('http://..../')\n      async for object in ijson.items(f, 'earth.europe.item'):\n         if object['type'] == 'city':\n            do_something_with(city)\n   asyncio.run(run())\n\nAn explicit set of ``*_async`` functions also exists\noffering the same functionality,\nexcept they will fail if anything other\nthan a file-like asynchronous object is given to them.\n(so the example above can also be written using ``ijson.items_async``).\nIn fact in ijson version 3.0\nthis was the only way to access\nthe ``asyncio`` support.\n\n\nIntercepting events\n-------------------\n\nThe four routines shown above\ninternally chain against each other:\ntuples generated by ``basic_parse``\nare the input for ``parse``,\nwhose results are the input to ``kvitems`` and ``items``.\n\nNormally users don't see this interaction,\nas they only care about the final output\nof the function they invoked,\nbut there are occasions when tapping\ninto this invocation chain this could be handy.\nThis is supported\nby passing the output of one function\n(i.e., an iterable of events, usually a generator)\nas the input of another,\nopening the door for user event filtering or injection.\n\nFor instance if one wants to skip some content\nbefore full item parsing:\n\n.. code-block:: python\n\n  import io\n  import ijson\n\n  parse_events = ijson.parse(io.BytesIO(b'[\"skip\", {\"a\": 1}, {\"b\": 2}, {\"c\": 3}]'))\n  while True:\n      prefix, event, value = next(parse_events)\n      if value == \"skip\":\n          break\n  for obj in ijson.items(parse_events, 'item'):\n      print(obj)\n\n\nNote that this interception\nonly makes sense for the ``basic_parse -> parse``,\n``parse -> items`` and ``parse -> kvitems`` interactions.\n\nNote also that event interception\nis currently not supported\nby the ``async`` functions.\n\n\nPush interfaces\n---------------\n\nAll examples above use a file-like object as the data input\n(both the normal case, and for ``asyncio`` support),\nand hence are \"pull\" interfaces,\nwith the library reading data as necessary.\nIf for whatever reason it's not possible to use such method,\nyou can still **push** data\nthrough yet a different interface: `coroutines <https://www.python.org/dev/peps/pep-0342/>`_\n(via generators, not ``asyncio`` coroutines).\nCoroutines effectively allow users\nto send data to them at any point in time,\nwith a final *target* coroutine-like object\nreceiving the results.\n\nIn the following example\nthe user is doing the reading\ninstead of letting the library do it:\n\n.. code-block:: python\n\n   import ijson\n\n   @ijson.coroutine\n   def print_cities():\n      while True:\n         obj = (yield)\n         if obj['type'] != 'city':\n            continue\n         print(obj)\n\n   coro = ijson.items_coro(print_cities(), 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n   coro.close()\n\nAll four ijson iterators\nhave a ``*_coro`` counterpart\nthat work by pushing data into them.\nInstead of receiving a file-like object\nand option buffer size as arguments,\nthey receive a single ``target`` argument,\nwhich should be a coroutine-like object\n(anything implementing a ``send`` method)\nthrough which results will be published.\n\nAn alternative to providing a coroutine\nis to use ``ijson.sendable_list`` to accumulate results,\nproviding the list is cleared after each parsing iteration,\nlike this:\n\n.. code-block:: python\n\n   import ijson\n\n   events = ijson.sendable_list()\n   coro = ijson.items_coro(events, 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n      process_accumulated_events(events)\n      del events[:]\n   coro.close()\n   process_accumulated_events(events)\n\n\nOptions\n=======\n\nAdditional options are supported by **all** ijson functions\nto give users more fine-grained control over certain operations:\n\n- The ``use_float`` option (defaults to ``False``)\n  controls how non-integer values are returned to the user.\n  If set to ``True`` users receive ``float()`` values;\n  otherwise ``Decimal`` values are constructed.\n  Note that building ``float`` values is usually faster,\n  but on the other hand there might be loss of precision\n  (which most applications will not care about)\n  and will raise an exception when overflow occurs\n  (e.g., if ``1e400`` is encountered).\n  This option also has the side-effect\n  that integer numbers bigger than ``2^64``\n  (but *sometimes* ``2^32``, see capabilities_)\n  will also raise an overflow error,\n  due to similar reasons.\n  Future versions of ijson\n  might change the default value of this option\n  to ``True``.\n- The ``multiple_values`` option (defaults to ``False``)\n  controls whether multiple top-level values are supported.\n  JSON content should contain a single top-level value\n  (see `the JSON Grammar <https://tools.ietf.org/html/rfc7159#section-2>`_).\n  However there are plenty of JSON files out in the wild\n  that contain multiple top-level values,\n  often separated by newlines.\n  By default ijson will fail to process these\n  with a ``parse error: trailing garbage`` error\n  unless ``multiple_values=True`` is specified.\n- Similarly the ``allow_comments`` option (defaults to ``False``)\n  controls whether C-style comments (e.g., ``/* a comment */``),\n  which are not supported by the JSON standard,\n  are allowed in the content or not.\n- For functions taking a file-like object,\n  an additional ``buf_size`` option (defaults to ``65536`` or 64KB)\n  specifies the amount of bytes the library\n  should attempt to read each time.\n- The ``items`` and ``kvitems`` functions, and all their variants,\n  have an optional ``map_type`` argument (defaults to ``dict``)\n  used to construct objects from the JSON stream.\n  This should be a dict-like type supporting item assignment.\n\n\nEvents\n======\n\nWhen using the lower-level ``ijson.parse`` function,\nthree-element tuples are generated\ncontaining a prefix, an event name, and a value.\nEvents will be one of the following:\n\n- ``start_map`` and ``end_map`` indicate\n  the beginning and end of a JSON object, respectively.\n  They carry a ``None`` as their value.\n- ``start_array`` and ``end_array`` indicate\n  the beginning and end of a JSON array, respectively.\n  They also carry a ``None`` as their value.\n- ``map_key`` indicates the name of a field in a JSON object.\n  Its associated value is the name itself.\n- ``null``, ``boolean``, ``integer``, ``double``, ``number`` and ``string``\n  all indicate actual content, which is stored in the associated value.\n\n\nPrefix\n======\n\nA prefix represents the context within a JSON document\nwhere an event originates at.\nIt works as follows:\n\n- It starts as an empty string.\n- A ``<name>`` part is appended when the parser starts parsing the contents\n  of a JSON object member called ``name``,\n  and removed once the content finishes.\n- A literal ``item`` part is appended when the parser is parsing\n  elements of a JSON array,\n  and removed when the array ends.\n- Parts are separated by ``.``.\n\nWhen using the ``ijson.items`` function,\nthe prefix works as the selection\nfor which objects should be automatically built and returned by ijson.\n\n\nBackends\n========\n\nIjson provides several implementations of the actual parsing in the form of\nbackends located in ijson/backends:\n\n- ``yajl2_c``: a C extension using `YAJL <http://lloyd.github.io/yajl/>`__ 2.x.\n  This is the fastest, but *might* require a compiler and the YAJL development files\n  to be present when installing this package.\n  Binary wheel distributions exist for major platforms/architectures to spare users\n  from having to compile the package.\n- ``yajl2_cffi``: wrapper around `YAJL <http://lloyd.github.io/yajl/>`__ 2.x\n  using CFFI.\n- ``yajl2``: wrapper around YAJL 2.x using ctypes, for when you can't use CFFI\n  for some reason.\n- ``yajl``: deprecated YAJL 1.x + ctypes wrapper, for even older systems.\n- ``python``: pure Python parser, good to use with PyPy\n\nThis list of backend names is available under the ``ijson.ALL_BACKENDS`` constant.\n\nYou can import a specific backend and use it in the same way as the top level\nlibrary:\n\n.. code-block::  python\n\n    import ijson.backends.yajl2_cffi as ijson\n\n    for item in ijson.items(...):\n        # ...\n\nImporting the top level library as ``import ijson``\nuses the first available backend in the same order of the list above,\nand its name is recorded under ``ijson.backend``.\nIf the ``IJSON_BACKEND`` environment variable is set\nits value takes precedence and is used to select the default backend.\n\nYou can also use the ``ijson.get_backend`` function\nto get a specific backend based on a name:\n\n.. code-block:: python\n\n    backend = ijson.get_backend('yajl2_c')\n    for item in backend.items(...):\n        # ...\n\n\nCapabilities\n------------\n\nApart from their performance,\nall backends are designed to support the same capabilities.\nThere are however some small known differences,\nall of which can be queried by inspecting\nthe ``capabilities`` module constant.\nIt contains the following members:\n\n* ``c_comments``: C-style comments are supported.\n* ``multiple_values``: multiple top-level JSON values are supported.\n* ``detects_invalid_leading_zeros``: numbers with leading zeroes\n  are reported as invalid (as they should, as pert the JSON standard),\n  raising a ``ValueError``.\n* ``detects_incomplete_json_tokens``: detects incomplete JSON tokens\n  at the end of an incomplete document (e.g., ``{\"a\": fals``),\n  raising an ``IncompleteJSONError``.\n* ``int64``: when using ``use_float=True``,\n    values greater than or equal to ``2^32`` are correctly returned.\n\nThese capabilities are supported by all backends,\nwith the following exceptions:\n\n* The ``yajl`` backend doesn't support ``multiple_values``,\n  ``detects_invalid_leading_zeros`` and ``detects_incomplete_json_tokens``.\n  It also doesn't support ``int64``\n  in platforms with a 32-bit C ``long`` type.\n\n* The ``python`` backend doesn't support ``c_comments``.\n\n\nPerformance tips\n================\n\nIn more-or-less decreasing order,\nthese are the most common actions you can take\nto ensure you get most of the performance\nout of ijson:\n\n- Make sure you use the fastest backend available.\n  See backends_ for details.\n- If you know your JSON data\n  contains only numbers that are \"well behaved\"\n  consider turning on the ``use_float`` option.\n  See options_ for details.\n- Make sure you feed ijson with binary data\n  instead of text data.\n  See faq_ #1 for details.\n- Play with the ``buf_size`` option,\n  as depending on your data source and your system\n  a value different from the default\n  might show better performance.\n  See options_ for details.\n\nThe benchmarking_ tool should help\nwith trying some of these options\nand observing their effect on your input files.\n\n\nFAQ\n===\n\n#. **Q**: Does ijson work with ``bytes`` or ``str`` values?\n\n   **A**: In short: both are accepted as input, outputs are only ``str``.\n\n   All ijson functions expecting a file-like object\n   should ideally be given one\n   that is opened in binary mode\n   (i.e., its ``read`` function returns ``bytes`` objects, not ``str``).\n   However if a text-mode file object is given\n   then the library will automatically\n   encode the strings into UTF-8 bytes.\n   A warning is currently issued (but not visible by default)\n   alerting users about this automatic conversion.\n\n   On the other hand ijson always returns text data\n   (JSON string values, object member names, event names, etc)\n   as ``str`` objects.\n   This mimics the behavior of the system ``json`` module.\n\n#. **Q**: How are numbers dealt with?\n\n   **A**: ijson returns ``int`` values for integers\n   and ``decimal.Decimal`` values for floating-point numbers.\n   This is mostly because of historical reasons.\n   Since 3.1 a new ``use_float`` option (defaults to ``False``)\n   is available to return ``float`` values instead.\n   See the options_ section for details.\n\n#. **Q**: I'm getting an ``UnicodeDecodeError``, or an ``IncompleteJSONError`` with no message\n\n   **A**: This error is caused by byte sequences that are not valid in UTF-8.\n   In other words, the data given to ijson is not *really* UTF-8 encoded,\n   or at least not properly.\n\n   Depending on where the data comes from you have different options:\n\n   * If you have control over the source of the data, fix it.\n\n   * If you have a way to intercept the data flow,\n     do so and pass it through a \"byte corrector\".\n     For instance, if you have a shell pipeline\n     feeding data through ``stdin`` into your process\n     you can add something like ``... | iconv -f utf8 -t utf8 -c | ...``\n     in between to correct invalid byte sequences.\n\n   * If you are working purely in python,\n     you can create a UTF-8 decoder\n     using codecs' `incrementaldecoder <https://docs.python.org/3/library/codecs.html#codecs.getincrementaldecoder>`_\n     to leniently decode your bytes into strings,\n     and feed those strings (using a file-like class) into ijson\n     (see our `string_reader_async internal class <https://github.com/ICRAR/ijson/blob/0157f3c65a7986970030d3faa75979ee205d3806/ijson/utils35.py#L19>`_\n     for some inspiration).\n\n   In the future ijson might offer something out of the box\n   to deal with invalid UTF-8 byte sequences.\n\n#. **Q**: I'm getting ``parse error: trailing garbage`` or ``Additional data found`` errors\n\n   **A**: This error signals that the input\n   contains more data than the top-level JSON value it's meant to contain.\n   This is *usually* caused by JSON data sources\n   containing multiple values, and is *usually* solved\n   by passing the ``multiple_values=True`` to the ijson function in use.\n   See the options_ section for details.\n\n#. How do I use ijson with the ``requests`` library\n\n   The ``requests`` library downloads the body of the HTTP response immediately by default.\n   Users wanting to feed the response into ijson\n   will need to override this behaviour\n   by using the ``requests.get(..., stream=True)`` parameter.\n   Then they have at least two options:\n\n   * Wrap the ``Response.iter_content()`` iterator into a file-like object,\n     then give that to ijson.\n\n   * Pass the ``Response.raw`` object (the underlying ``socket.socket``) to ijson.\n\n   The first alternative is best, since ``requests`` will automatically decode\n   any HTTP transfer encodings, which doesn't happen with ``Response.raw``.\n   See `Iterator support`_ for how to wrap ``Response.iter_content()``\n   into a file-like object.\n\n\nAcknowledgements\n================\n\nijson was originally developed and actively maintained until 2016\nby `Ivan Sagalaev <http://softwaremaniacs.org/>`_.\nIn 2019 he\n`handed over <https://github.com/isagalaev/ijson/pull/58#issuecomment-500596815>`_\nthe maintenance of the project and the PyPI ownership.\n\nPython parser in ijson is relatively simple thanks to `Douglas Crockford\n<http://www.crockford.com/>`_ who invented a strict, easy to parse syntax.\n\nThe `YAJL <https://lloyd.github.io/yajl>`__ library by `Lloyd Hilaiel\n<http://lloyd.io/>`_ is the most popular and efficient way to parse JSON in an\niterative fashion.\nWhen building the library ourselves,\nwe use `our own fork <https://github.com/rtobar/yajl>`__\nthat contains fixes for all known CVEs.\n\nIjson was inspired by `yajl-py <http://pykler.github.com/yajl-py/>`_ wrapper by\n`Hatem Nassrat <http://www.nassrat.ca/>`_. Though ijson borrows almost nothing\nfrom the actual yajl-py code it was used as an example of integration with yajl\nusing ctypes.\n",
      "keywords": "",
      "platform": [],
      "classifiers": [
        "Development Status :: 5 - Production/Stable",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Programming Language :: Python :: 3.13",
        "Programming Language :: Python :: 3.14",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Environment :: MetaData :: IBM Python Ecosystem"
      ],
      "download_url": "",
      "supported_platform": [],
      "comment": "",
      "provides": [],
      "requires": [],
      "obsoletes": [],
      "project_urls": [
        "Homepage, https://github.com/ICRAR/ijson"
      ],
      "provides_dist": [],
      "obsoletes_dist": [],
      "requires_dist": [],
      "requires_external": [],
      "requires_python": ">=3.9",
      "description_content_type": "text/x-rst",
      "provides_extras": [],
      "dynamic": [
        "license-file"
      ],
      "license_expression": "BSD-3-Clause AND ISC",
      "license_file": [
        "LICENSE.txt"
      ],
      "+links": [
        {
          "rel": "releasefile",
          "hash_spec": "sha256=479186eab14e2c014c01019e702a8150568bade6b854c1ee41f0cf4d0d2e516e",
          "hashes": {
            "sha256": "479186eab14e2c014c01019e702a8150568bade6b854c1ee41f0cf4d0d2e516e"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/479/186eab14e2c01/ijson-3.4.0.post0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                38
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=ce775936e5e13d6546e925dd84f47875e257dc03edd5028bb8d531d8b48bd43c",
          "hashes": {
            "sha256": "ce775936e5e13d6546e925dd84f47875e257dc03edd5028bb8d531d8b48bd43c"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/ce7/75936e5e13d65/ijson-3.4.0.post0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                38
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=e087a75145dc03aa520064ffc799f3763215f311cbf12c04c30add5427775f8b",
          "hashes": {
            "sha256": "e087a75145dc03aa520064ffc799f3763215f311cbf12c04c30add5427775f8b"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/e08/7a75145dc03aa/ijson-3.4.0.post0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                38
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=48428b0bbf5ad0c2846ac9ba5c0f60a134767e63ab78e3f2c555d7857674aec4",
          "hashes": {
            "sha256": "48428b0bbf5ad0c2846ac9ba5c0f60a134767e63ab78e3f2c555d7857674aec4"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/484/28b0bbf5ad0c2/ijson-3.4.0.post0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                39
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=cfc8625f1cb7800fd20cbb27ea4d4b7c9c6dffd894a4cc1587c24a2b7b013275",
          "hashes": {
            "sha256": "cfc8625f1cb7800fd20cbb27ea4d4b7c9c6dffd894a4cc1587c24a2b7b013275"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/cfc/8625f1cb7800f/ijson-3.4.0.post0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                39
              ],
              "dst": "ppc64le/linux"
            }
          ]
        }
      ]
    },
    "3.4.0.post0+ppc64le1": {
      "name": "ijson",
      "version": "3.4.0.post0+ppc64le1",
      "metadata_version": "2.4",
      "summary": "Iterative JSON parser with standard Python iterator interfaces",
      "home_page": "",
      "author": "",
      "author_email": "Rodrigo Tobar <rtobar@icrar.org>, Ivan Sagalaev <maniac@softwaremaniacs.org>",
      "maintainer": "",
      "maintainer_email": "",
      "license": "",
      "description": ".. image:: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://github.com/ICRAR/ijson/actions/workflows/fast-built-and-test.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://coveralls.io/repos/github/ICRAR/ijson/badge.svg?branch=master\n    :target: https://coveralls.io/github/ICRAR/ijson?branch=master\n\n.. image:: https://badge.fury.io/py/ijson.svg\n    :target: https://badge.fury.io/py/ijson\n\n.. image:: https://img.shields.io/pypi/pyversions/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dd/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dw/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dm/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n\n=====\nijson\n=====\n\nIjson is an iterative JSON parser with standard Python iterator interfaces.\n\n.. contents::\n   :local:\n\n\nInstallation\n============\n\nIjson is hosted in PyPI, so you should be able to install it via ``pip``::\n\n  pip install ijson\n\nBinary wheels are provided\nfor major platforms\nand python versions.\nThese are built and published automatically\nusing `cibuildwheel <https://cibuildwheel.readthedocs.io/en/stable/>`_\nvia GitHub Actions.\n\n\nUsage\n=====\n\nAll usage example will be using a JSON document describing geographical\nobjects:\n\n.. code-block:: json\n\n    {\n      \"earth\": {\n        \"europe\": [\n          {\"name\": \"Paris\", \"type\": \"city\", \"info\": { ... }},\n          {\"name\": \"Thames\", \"type\": \"river\", \"info\": { ... }},\n          // ...\n        ],\n        \"america\": [\n          {\"name\": \"Texas\", \"type\": \"state\", \"info\": { ... }},\n          // ...\n        ]\n      }\n    }\n\n\nHigh-level interfaces\n---------------------\n\nijson works by continuously reading data from a JSON stream provided by the user.\nThis is presented as a file-like object.\nIn particular it must provide a ``read(size)`` method\nreturning either ``bytes`` (preferably) or ``str``.\nExample file-like objects are\nfiles opened with ``open``,\nHTTP/HTTPS requests made using ``urllib.request.urlopen``,\n``socket.socket`` objects,\nand more.\n\nThe most common usage of ijson is to yield native Python objects\nlocated under a prefix.\nThis is done using the ``items`` function.\nHere's how to process all European cities:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    objects = ijson.items(f, 'earth.europe.item')\n    cities = (o for o in objects if o['type'] == 'city')\n    for city in cities:\n        do_something_with(city)\n\nFor how to build a prefix see the prefix_ section below.\n\nOther times it might be useful to iterate over object members\nrather than objects themselves (e.g., when objects are too big).\nIn that case one can use the ``kvitems`` function instead:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    european_places = ijson.kvitems(f, 'earth.europe.item')\n    names = (v for k, v in european_places if k == 'name')\n    for name in names:\n        do_something_with(name)\n\n\nLower-level interfaces\n----------------------\n\nSometimes when dealing with a particularly large JSON payload it may worth to\nnot even construct individual Python objects and react on individual events\nimmediately producing some result.\nThis is achieved using the ``parse`` function:\n\n.. code-block::  python\n\n    import ijson\n\n    parser = ijson.parse(urlopen('http://.../'))\n    stream.write('<geo>')\n    for prefix, event, value in parser:\n        if (prefix, event) == ('earth', 'map_key'):\n            stream.write('<%s>' % value)\n            continent = value\n        elif prefix.endswith('.name'):\n            stream.write('<object name=\"%s\"/>' % value)\n        elif (prefix, event) == ('earth.%s' % continent, 'end_map'):\n            stream.write('</%s>' % continent)\n    stream.write('</geo>')\n\nEven more bare-bones is the ability to react on individual events\nwithout even calculating a prefix\nusing the ``basic_parse`` function:\n\n.. code-block:: python\n\n    import ijson\n\n    events = ijson.basic_parse(urlopen('http://.../'))\n    num_names = sum(1 for event, value in events\n                    if event == 'map_key' and value == 'name')\n\n\nCommand line\n------------\n\nA command line utility is included with ijson\nto help visualise the output of each of the routines above.\nIt reads JSON from the standard input,\nand it prints the results of the parsing method chosen by the user\nto the standard output.\n\nThe tool is available by running the ``ijson.dump`` module.\nFor example::\n\n $> echo '{\"A\": 0, \"B\": [1, 2, 3, 4]}' | python -m ijson.dump -m parse\n #: path, name, value\n --------------------\n 0: , start_map, None\n 1: , map_key, A\n 2: A, number, 0\n 3: , map_key, B\n 4: B, start_array, None\n 5: B.item, number, 1\n 6: B.item, number, 2\n 7: B.item, number, 3\n 8: B.item, number, 4\n 9: B, end_array, None\n 10: , end_map, None\n\nUsing ``-h/--help`` will show all available options.\n\n\nBenchmarking\n------------\n\nA command line utility is included with ijson\nto help benchmarking the different methods offered by the package.\nIt offers some built-in example inputs\nthat try to mimic different scenarios,\nbut more importantly it also supports user-provided inputs.\nYou can also specify which backends to time,\nnumber of iterations,\nand more.\n\nThe tool is available by running the ``ijson.benchmark`` module.\nFor example::\n\n $> python -m ijson.benchmark my/json/file.json -m items -p values.item\n\nUsing ``-h/--help`` will show all available options.\n\n\n``bytes``/``str`` support\n-------------------------\n\nAlthough not usually how they are meant to be run,\nall the functions above also accept\n``bytes`` and ``str`` objects\ndirectly as inputs.\nThese are then internally wrapped into a file object,\nand further processed.\nThis is useful for testing and prototyping,\nbut probably not extremely useful in real-life scenarios.\n\n\nIterator support\n----------------\n\nIn many situations the direct input users want to pass to ijson\nis an iterator (e.g., a generator) rather than a file-like object.\nTo bridge this gap users need to adapt the iterator into a file-like object.\nExamples of this can be found\n`here <https://github.com/ICRAR/ijson/issues/44#issuecomment-1771013830>`__\nand `here <https://github.com/ICRAR/ijson/issues/58#issuecomment-917655522>`__.\nFuture versions of ijson might provide built-in adapters for this,\nand/or support iterators without the need to adapt them first.\n\n\n``asyncio`` support\n-------------------\n\nAll of the methods above\nwork also on file-like asynchronous objects,\nso they can be iterated asynchronously.\nIn other words, something like this:\n\n.. code-block:: python\n\n   import asyncio\n   import ijson\n\n   async def run():\n      f = await async_urlopen('http://..../')\n      async for object in ijson.items(f, 'earth.europe.item'):\n         if object['type'] == 'city':\n            do_something_with(city)\n   asyncio.run(run())\n\nAn explicit set of ``*_async`` functions also exists\noffering the same functionality,\nexcept they will fail if anything other\nthan a file-like asynchronous object is given to them.\n(so the example above can also be written using ``ijson.items_async``).\nIn fact in ijson version 3.0\nthis was the only way to access\nthe ``asyncio`` support.\n\n\nIntercepting events\n-------------------\n\nThe four routines shown above\ninternally chain against each other:\ntuples generated by ``basic_parse``\nare the input for ``parse``,\nwhose results are the input to ``kvitems`` and ``items``.\n\nNormally users don't see this interaction,\nas they only care about the final output\nof the function they invoked,\nbut there are occasions when tapping\ninto this invocation chain this could be handy.\nThis is supported\nby passing the output of one function\n(i.e., an iterable of events, usually a generator)\nas the input of another,\nopening the door for user event filtering or injection.\n\nFor instance if one wants to skip some content\nbefore full item parsing:\n\n.. code-block:: python\n\n  import io\n  import ijson\n\n  parse_events = ijson.parse(io.BytesIO(b'[\"skip\", {\"a\": 1}, {\"b\": 2}, {\"c\": 3}]'))\n  while True:\n      prefix, event, value = next(parse_events)\n      if value == \"skip\":\n          break\n  for obj in ijson.items(parse_events, 'item'):\n      print(obj)\n\n\nNote that this interception\nonly makes sense for the ``basic_parse -> parse``,\n``parse -> items`` and ``parse -> kvitems`` interactions.\n\nNote also that event interception\nis currently not supported\nby the ``async`` functions.\n\n\nPush interfaces\n---------------\n\nAll examples above use a file-like object as the data input\n(both the normal case, and for ``asyncio`` support),\nand hence are \"pull\" interfaces,\nwith the library reading data as necessary.\nIf for whatever reason it's not possible to use such method,\nyou can still **push** data\nthrough yet a different interface: `coroutines <https://www.python.org/dev/peps/pep-0342/>`_\n(via generators, not ``asyncio`` coroutines).\nCoroutines effectively allow users\nto send data to them at any point in time,\nwith a final *target* coroutine-like object\nreceiving the results.\n\nIn the following example\nthe user is doing the reading\ninstead of letting the library do it:\n\n.. code-block:: python\n\n   import ijson\n\n   @ijson.coroutine\n   def print_cities():\n      while True:\n         obj = (yield)\n         if obj['type'] != 'city':\n            continue\n         print(obj)\n\n   coro = ijson.items_coro(print_cities(), 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n   coro.close()\n\nAll four ijson iterators\nhave a ``*_coro`` counterpart\nthat work by pushing data into them.\nInstead of receiving a file-like object\nand option buffer size as arguments,\nthey receive a single ``target`` argument,\nwhich should be a coroutine-like object\n(anything implementing a ``send`` method)\nthrough which results will be published.\n\nAn alternative to providing a coroutine\nis to use ``ijson.sendable_list`` to accumulate results,\nproviding the list is cleared after each parsing iteration,\nlike this:\n\n.. code-block:: python\n\n   import ijson\n\n   events = ijson.sendable_list()\n   coro = ijson.items_coro(events, 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n      process_accumulated_events(events)\n      del events[:]\n   coro.close()\n   process_accumulated_events(events)\n\n\nOptions\n=======\n\nAdditional options are supported by **all** ijson functions\nto give users more fine-grained control over certain operations:\n\n- The ``use_float`` option (defaults to ``False``)\n  controls how non-integer values are returned to the user.\n  If set to ``True`` users receive ``float()`` values;\n  otherwise ``Decimal`` values are constructed.\n  Note that building ``float`` values is usually faster,\n  but on the other hand there might be loss of precision\n  (which most applications will not care about)\n  and will raise an exception when overflow occurs\n  (e.g., if ``1e400`` is encountered).\n  This option also has the side-effect\n  that integer numbers bigger than ``2^64``\n  (but *sometimes* ``2^32``, see capabilities_)\n  will also raise an overflow error,\n  due to similar reasons.\n  Future versions of ijson\n  might change the default value of this option\n  to ``True``.\n- The ``multiple_values`` option (defaults to ``False``)\n  controls whether multiple top-level values are supported.\n  JSON content should contain a single top-level value\n  (see `the JSON Grammar <https://tools.ietf.org/html/rfc7159#section-2>`_).\n  However there are plenty of JSON files out in the wild\n  that contain multiple top-level values,\n  often separated by newlines.\n  By default ijson will fail to process these\n  with a ``parse error: trailing garbage`` error\n  unless ``multiple_values=True`` is specified.\n- Similarly the ``allow_comments`` option (defaults to ``False``)\n  controls whether C-style comments (e.g., ``/* a comment */``),\n  which are not supported by the JSON standard,\n  are allowed in the content or not.\n- For functions taking a file-like object,\n  an additional ``buf_size`` option (defaults to ``65536`` or 64KB)\n  specifies the amount of bytes the library\n  should attempt to read each time.\n- The ``items`` and ``kvitems`` functions, and all their variants,\n  have an optional ``map_type`` argument (defaults to ``dict``)\n  used to construct objects from the JSON stream.\n  This should be a dict-like type supporting item assignment.\n\n\nEvents\n======\n\nWhen using the lower-level ``ijson.parse`` function,\nthree-element tuples are generated\ncontaining a prefix, an event name, and a value.\nEvents will be one of the following:\n\n- ``start_map`` and ``end_map`` indicate\n  the beginning and end of a JSON object, respectively.\n  They carry a ``None`` as their value.\n- ``start_array`` and ``end_array`` indicate\n  the beginning and end of a JSON array, respectively.\n  They also carry a ``None`` as their value.\n- ``map_key`` indicates the name of a field in a JSON object.\n  Its associated value is the name itself.\n- ``null``, ``boolean``, ``integer``, ``double``, ``number`` and ``string``\n  all indicate actual content, which is stored in the associated value.\n\n\nPrefix\n======\n\nA prefix represents the context within a JSON document\nwhere an event originates at.\nIt works as follows:\n\n- It starts as an empty string.\n- A ``<name>`` part is appended when the parser starts parsing the contents\n  of a JSON object member called ``name``,\n  and removed once the content finishes.\n- A literal ``item`` part is appended when the parser is parsing\n  elements of a JSON array,\n  and removed when the array ends.\n- Parts are separated by ``.``.\n\nWhen using the ``ijson.items`` function,\nthe prefix works as the selection\nfor which objects should be automatically built and returned by ijson.\n\n\nBackends\n========\n\nIjson provides several implementations of the actual parsing in the form of\nbackends located in ijson/backends:\n\n- ``yajl2_c``: a C extension using `YAJL <http://lloyd.github.io/yajl/>`__ 2.x.\n  This is the fastest, but *might* require a compiler and the YAJL development files\n  to be present when installing this package.\n  Binary wheel distributions exist for major platforms/architectures to spare users\n  from having to compile the package.\n- ``yajl2_cffi``: wrapper around `YAJL <http://lloyd.github.io/yajl/>`__ 2.x\n  using CFFI.\n- ``yajl2``: wrapper around YAJL 2.x using ctypes, for when you can't use CFFI\n  for some reason.\n- ``yajl``: deprecated YAJL 1.x + ctypes wrapper, for even older systems.\n- ``python``: pure Python parser, good to use with PyPy\n\nThis list of backend names is available under the ``ijson.ALL_BACKENDS`` constant.\n\nYou can import a specific backend and use it in the same way as the top level\nlibrary:\n\n.. code-block::  python\n\n    import ijson.backends.yajl2_cffi as ijson\n\n    for item in ijson.items(...):\n        # ...\n\nImporting the top level library as ``import ijson``\nuses the first available backend in the same order of the list above,\nand its name is recorded under ``ijson.backend``.\nIf the ``IJSON_BACKEND`` environment variable is set\nits value takes precedence and is used to select the default backend.\n\nYou can also use the ``ijson.get_backend`` function\nto get a specific backend based on a name:\n\n.. code-block:: python\n\n    backend = ijson.get_backend('yajl2_c')\n    for item in backend.items(...):\n        # ...\n\n\nCapabilities\n------------\n\nApart from their performance,\nall backends are designed to support the same capabilities.\nThere are however some small known differences,\nall of which can be queried by inspecting\nthe ``capabilities`` module constant.\nIt contains the following members:\n\n* ``c_comments``: C-style comments are supported.\n* ``multiple_values``: multiple top-level JSON values are supported.\n* ``detects_invalid_leading_zeros``: numbers with leading zeroes\n  are reported as invalid (as they should, as pert the JSON standard),\n  raising a ``ValueError``.\n* ``detects_incomplete_json_tokens``: detects incomplete JSON tokens\n  at the end of an incomplete document (e.g., ``{\"a\": fals``),\n  raising an ``IncompleteJSONError``.\n* ``int64``: when using ``use_float=True``,\n    values greater than or equal to ``2^32`` are correctly returned.\n\nThese capabilities are supported by all backends,\nwith the following exceptions:\n\n* The ``yajl`` backend doesn't support ``multiple_values``,\n  ``detects_invalid_leading_zeros`` and ``detects_incomplete_json_tokens``.\n  It also doesn't support ``int64``\n  in platforms with a 32-bit C ``long`` type.\n\n* The ``python`` backend doesn't support ``c_comments``.\n\n\nPerformance tips\n================\n\nIn more-or-less decreasing order,\nthese are the most common actions you can take\nto ensure you get most of the performance\nout of ijson:\n\n- Make sure you use the fastest backend available.\n  See backends_ for details.\n- If you know your JSON data\n  contains only numbers that are \"well behaved\"\n  consider turning on the ``use_float`` option.\n  See options_ for details.\n- Make sure you feed ijson with binary data\n  instead of text data.\n  See faq_ #1 for details.\n- Play with the ``buf_size`` option,\n  as depending on your data source and your system\n  a value different from the default\n  might show better performance.\n  See options_ for details.\n\nThe benchmarking_ tool should help\nwith trying some of these options\nand observing their effect on your input files.\n\n\nFAQ\n===\n\n#. **Q**: Does ijson work with ``bytes`` or ``str`` values?\n\n   **A**: In short: both are accepted as input, outputs are only ``str``.\n\n   All ijson functions expecting a file-like object\n   should ideally be given one\n   that is opened in binary mode\n   (i.e., its ``read`` function returns ``bytes`` objects, not ``str``).\n   However if a text-mode file object is given\n   then the library will automatically\n   encode the strings into UTF-8 bytes.\n   A warning is currently issued (but not visible by default)\n   alerting users about this automatic conversion.\n\n   On the other hand ijson always returns text data\n   (JSON string values, object member names, event names, etc)\n   as ``str`` objects.\n   This mimics the behavior of the system ``json`` module.\n\n#. **Q**: How are numbers dealt with?\n\n   **A**: ijson returns ``int`` values for integers\n   and ``decimal.Decimal`` values for floating-point numbers.\n   This is mostly because of historical reasons.\n   Since 3.1 a new ``use_float`` option (defaults to ``False``)\n   is available to return ``float`` values instead.\n   See the options_ section for details.\n\n#. **Q**: I'm getting an ``UnicodeDecodeError``, or an ``IncompleteJSONError`` with no message\n\n   **A**: This error is caused by byte sequences that are not valid in UTF-8.\n   In other words, the data given to ijson is not *really* UTF-8 encoded,\n   or at least not properly.\n\n   Depending on where the data comes from you have different options:\n\n   * If you have control over the source of the data, fix it.\n\n   * If you have a way to intercept the data flow,\n     do so and pass it through a \"byte corrector\".\n     For instance, if you have a shell pipeline\n     feeding data through ``stdin`` into your process\n     you can add something like ``... | iconv -f utf8 -t utf8 -c | ...``\n     in between to correct invalid byte sequences.\n\n   * If you are working purely in python,\n     you can create a UTF-8 decoder\n     using codecs' `incrementaldecoder <https://docs.python.org/3/library/codecs.html#codecs.getincrementaldecoder>`_\n     to leniently decode your bytes into strings,\n     and feed those strings (using a file-like class) into ijson\n     (see our `string_reader_async internal class <https://github.com/ICRAR/ijson/blob/0157f3c65a7986970030d3faa75979ee205d3806/ijson/utils35.py#L19>`_\n     for some inspiration).\n\n   In the future ijson might offer something out of the box\n   to deal with invalid UTF-8 byte sequences.\n\n#. **Q**: I'm getting ``parse error: trailing garbage`` or ``Additional data found`` errors\n\n   **A**: This error signals that the input\n   contains more data than the top-level JSON value it's meant to contain.\n   This is *usually* caused by JSON data sources\n   containing multiple values, and is *usually* solved\n   by passing the ``multiple_values=True`` to the ijson function in use.\n   See the options_ section for details.\n\n#. How do I use ijson with the ``requests`` library\n\n   The ``requests`` library downloads the body of the HTTP response immediately by default.\n   Users wanting to feed the response into ijson\n   will need to override this behaviour\n   by using the ``requests.get(..., stream=True)`` parameter.\n   Then they have at least two options:\n\n   * Wrap the ``Response.iter_content()`` iterator into a file-like object,\n     then give that to ijson.\n\n   * Pass the ``Response.raw`` object (the underlying ``socket.socket``) to ijson.\n\n   The first alternative is best, since ``requests`` will automatically decode\n   any HTTP transfer encodings, which doesn't happen with ``Response.raw``.\n   See `Iterator support`_ for how to wrap ``Response.iter_content()``\n   into a file-like object.\n\n\nAcknowledgements\n================\n\nijson was originally developed and actively maintained until 2016\nby `Ivan Sagalaev <http://softwaremaniacs.org/>`_.\nIn 2019 he\n`handed over <https://github.com/isagalaev/ijson/pull/58#issuecomment-500596815>`_\nthe maintenance of the project and the PyPI ownership.\n\nPython parser in ijson is relatively simple thanks to `Douglas Crockford\n<http://www.crockford.com/>`_ who invented a strict, easy to parse syntax.\n\nThe `YAJL <https://lloyd.github.io/yajl>`__ library by `Lloyd Hilaiel\n<http://lloyd.io/>`_ is the most popular and efficient way to parse JSON in an\niterative fashion.\nWhen building the library ourselves,\nwe use `our own fork <https://github.com/rtobar/yajl>`__\nthat contains fixes for all known CVEs.\n\nIjson was inspired by `yajl-py <http://pykler.github.com/yajl-py/>`_ wrapper by\n`Hatem Nassrat <http://www.nassrat.ca/>`_. Though ijson borrows almost nothing\nfrom the actual yajl-py code it was used as an example of integration with yajl\nusing ctypes.\n",
      "keywords": "",
      "platform": [],
      "classifiers": [
        "Development Status :: 5 - Production/Stable",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Programming Language :: Python :: 3.13",
        "Programming Language :: Python :: 3.14",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Environment :: MetaData :: IBM Python Ecosystem"
      ],
      "download_url": "",
      "supported_platform": [],
      "comment": "",
      "provides": [],
      "requires": [],
      "obsoletes": [],
      "project_urls": [
        "Homepage, https://github.com/ICRAR/ijson"
      ],
      "provides_dist": [],
      "obsoletes_dist": [],
      "requires_dist": [],
      "requires_external": [],
      "requires_python": ">=3.9",
      "description_content_type": "text/x-rst",
      "provides_extras": "",
      "dynamic": "license-file",
      "license_expression": "BSD-3-Clause AND ISC",
      "license_file": "LICENSE.txt",
      "+links": [
        {
          "rel": "releasefile",
          "hash_spec": "sha256=04fc04b89a0891cc3dc1a8b033616f9968399569a0043aa5177389943101bb35",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/04f/c04b89a0891cc/ijson-3.4.0.post0+ppc64le1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                11
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=a4b20652e6d77f7074f986cecb4973df9f7b09ad0565715be5c42b3347a31f7a",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/a4b/20652e6d77f70/ijson-3.4.0.post0+ppc64le1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                11
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=743a2d6afb9dd13344c51772d979477139de461ecdf8c953a9ebc3a3b140df1f",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/743/a2d6afb9dd133/ijson-3.4.0.post0+ppc64le1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                12
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=7b165d1c8e40c3d86af5eb90fd147fb0fb999d68f5a3821d65ba23b655a32597",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/7b1/65d1c8e40c3d8/ijson-3.4.0.post0+ppc64le1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                12
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=33bd84ddc3a8131d3ed11fbedf72ade9389297dd54614ee6487889a80ca48d10",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/33b/d84ddc3a8131d/ijson-3.4.0.post0+ppc64le1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                12
              ],
              "dst": "ppc64le/linux"
            }
          ]
        }
      ]
    },
    "3.1.4+ppc64le1": {
      "name": "ijson",
      "version": "3.1.4+ppc64le1",
      "metadata_version": "2.1",
      "summary": "Iterative JSON parser with standard Python iterator interfaces",
      "home_page": "https://github.com/ICRAR/ijson",
      "author": "Rodrigo Tobar, Ivan Sagalaev",
      "author_email": "rtobar@icrar.org, maniac@softwaremaniacs.org",
      "maintainer": "",
      "maintainer_email": "",
      "license": "BSD",
      "description": ".. image:: https://travis-ci.com/ICRAR/ijson.svg?branch=master\n    :target: https://travis-ci.com/ICRAR/ijson\n\n.. image:: https://ci.appveyor.com/api/projects/status/32wiho6ojw3eakp8/branch/master?svg=true\n    :target: https://ci.appveyor.com/project/rtobar/ijson/branch/master\n\n.. image:: https://coveralls.io/repos/github/ICRAR/ijson/badge.svg?branch=master\n    :target: https://coveralls.io/github/ICRAR/ijson?branch=master\n\n.. image:: https://badge.fury.io/py/ijson.svg\n    :target: https://badge.fury.io/py/ijson\n\n.. image:: https://img.shields.io/pypi/pyversions/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dd/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dw/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dm/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n\n=====\nijson\n=====\n\nIjson is an iterative JSON parser with standard Python iterator interfaces.\n\n.. contents::\n   :local:\n\n\nInstallation\n============\n\nIjson is hosted in PyPI, so you should be able to install it via ``pip``::\n\n  pip install ijson\n\nBinary wheels are provided\nfor major platforms (Linux, MacOS, Windows)\nand python versions (2.7, 3.5+).\nThese are built and published automatically\nusing `cibuildwheel <https://cibuildwheel.readthedocs.io/en/stable/>`_\nvia Travis CI.\n\n\nUsage\n=====\n\nAll usage example will be using a JSON document describing geographical\nobjects:\n\n.. code-block:: json\n\n    {\n      \"earth\": {\n        \"europe\": [\n          {\"name\": \"Paris\", \"type\": \"city\", \"info\": { ... }},\n          {\"name\": \"Thames\", \"type\": \"river\", \"info\": { ... }},\n          // ...\n        ],\n        \"america\": [\n          {\"name\": \"Texas\", \"type\": \"state\", \"info\": { ... }},\n          // ...\n        ]\n      }\n    }\n\n\nHigh-level interfaces\n---------------------\n\nMost common usage is having ijson yield native Python objects out of a JSON\nstream located under a prefix.\nThis is done using the ``items`` function.\nHere's how to process all European cities:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    objects = ijson.items(f, 'earth.europe.item')\n    cities = (o for o in objects if o['type'] == 'city')\n    for city in cities:\n        do_something_with(city)\n\nFor how to build a prefix see the prefix_ section below.\n\nOther times it might be useful to iterate over object members\nrather than objects themselves (e.g., when objects are too big).\nIn that case one can use the ``kvitems`` function instead:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    european_places = ijson.kvitems(f, 'earth.europe.item')\n    names = (v for k, v in european_places if k == 'name')\n    for name in names:\n        do_something_with(name)\n\n\nLower-level interfaces\n----------------------\n\nSometimes when dealing with a particularly large JSON payload it may worth to\nnot even construct individual Python objects and react on individual events\nimmediately producing some result.\nThis is achieved using the ``parse`` function:\n\n.. code-block::  python\n\n    import ijson\n\n    parser = ijson.parse(urlopen('http://.../'))\n    stream.write('<geo>')\n    for prefix, event, value in parser:\n        if (prefix, event) == ('earth', 'map_key'):\n            stream.write('<%s>' % value)\n            continent = value\n        elif prefix.endswith('.name'):\n            stream.write('<object name=\"%s\"/>' % value)\n        elif (prefix, event) == ('earth.%s' % continent, 'end_map'):\n            stream.write('</%s>' % continent)\n    stream.write('</geo>')\n\nEven more bare-bones is the ability to react on individual events\nwithout even calculating a prefix\nusing the ``basic_parse`` function:\n\n.. code-block:: python\n\n    import ijson\n\n    events = ijson.basic_parse(urlopen('http://.../'))\n    num_names = sum(1 for event, value in events\n                    if event == 'map_key' and value == 'name')\n\n\n``bytes``/``str`` support\n-------------------------\n\nAlthough not usually how they are meant to be run,\nall the functions above also accept\n``bytes`` and ``str`` objects (and ``unicode`` in python 2.7)\ndirectly as inputs.\nThese are then internally wrapped into a file object,\nand further processed.\nThis is useful for testing and prototyping,\nbut probably not extremely useful in real-life scenarios.\n\n\n``asyncio`` support\n-------------------\n\nIn python 3.5+ all of the methods above\nwork also on file-like asynchronous objects,\nso they can be iterated asynchronously.\nIn other words, something like this:\n\n.. code-block:: python\n\n   import asyncio\n   import ijson\n\n   async def run():\n      f = await async_urlopen('http://..../')\n      async for object in ijson.items(f, 'earth.europe.item'):\n         if object['type'] == 'city':\n            do_something_with(city)\n   asyncio.run(run())\n\nAn explicit set of ``*_async`` functions also exists\noffering the same functionality,\nexcept they will fail if anything other\nthan a file-like asynchronous object is given to them.\n(so the example above can also be written using ``ijson.items_async``).\nIn fact in ijson version 3.0\nthis was the only way to access\nthe ``asyncio`` support.\n\n\nIntercepting events\n-------------------\n\nThe four routines shown above\ninternally chain against each other:\ntuples generated by ``basic_parse``\nare the input for ``parse``,\nwhose results are the input to ``kvitems`` and ``items``.\n\nNormally users don't see this interaction,\nas they only care about the final output\nof the function they invoked,\nbut there are occasions when tapping\ninto this invocation chain this could be handy.\nThis is supported\nby passing the output of one function\n(i.e., an iterable of events, usually a generator)\nas the input of another,\nopening the door for user event filtering or injection.\n\nFor instance if one wants to skip some content\nbefore full item parsing:\n\n.. code-block:: python\n\n  import io\n  import ijson\n\n  parse_events = ijson.parse(io.BytesIO(b'[\"skip\", {\"a\": 1}, {\"b\": 2}, {\"c\": 3}]'))\n  while True:\n      prefix, event, value = next(parse_event)\n      if value == \"skip\":\n          break\n  for obj in ijson.items(parse_events, 'item')\n      print(obj)\n\n\nNote that this interception\nonly makes sense for the ``basic_parse -> parse``,\n``parse -> items`` and ``parse -> kvitems`` interactions.\n\n\nPush interfaces\n---------------\n\nAll examples above use a file-like object as the data input\n(both the normal case, and for ``asyncio`` support),\nand hence are \"pull\" interfaces,\nwith the library reading data as necessary.\nIf for whatever reason it's not possible to use such method,\nyou can still **push** data\nthrough yet a different interface: `coroutines <https://www.python.org/dev/peps/pep-0342/>`_\n(via generators, not ``asyncio`` coroutines).\nCoroutines effectively allow users\nto send data to them at any point in time,\nwith a final *target* coroutine-like object\nreceiving the results.\n\nIn the following example\nthe user is doing the reading\ninstead of letting the library do it:\n\n.. code-block:: python\n\n   import ijson\n\n   @ijson.coroutine\n   def print_cities():\n      while True:\n         obj = (yield)\n         if obj['type'] != 'city':\n            continue\n         print(obj)\n\n   coro = ijson.items_coro(print_cities(), 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n   coro.close()\n\nAll four ijson iterators\nhave a ``*_coro`` counterpart\nthat work by pushing data into them.\nInstead of receiving a file-like object\nand option buffer size as arguments,\nthey receive a single ``target`` argument,\nwhich should be a coroutine-like object\n(anything implementing a ``send`` method)\nthrough which results will be published.\n\nAn alternative to providing a coroutine\nis to use ``ijson.sendable_list`` to accumulate results,\nproviding the list is cleared after each parsing iteration,\nlike this:\n\n.. code-block:: python\n\n   import ijson\n\n   events = ijson.sendable_list()\n   coro = ijson.items_coro(events, 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n      process_accumulated_events(events)\n      del events[:]\n   coro.close()\n   process_accumulated_events(events)\n\n\n.. _options:\n\nOptions\n=======\n\nAdditional options are supported by **all** ijson functions\nto give users more fine-grained control over certain operations:\n\n- The ``use_float`` option (defaults to ``False``)\n  controls how non-integer values are returned to the user.\n  If set to ``True`` users receive ``float()`` values;\n  otherwise ``Decimal`` values are constructed.\n  Note that building ``float`` values is usually faster,\n  but on the other hand there might be loss of precision\n  (which most applications will not care about)\n  and will raise an exception when overflow occurs\n  (e.g., if ``1e400`` is encountered).\n  This option also has the side-effect\n  that integer numbers bigger than ``2^64``\n  (but *sometimes* ``2^32``, see backends_)\n  will also raise an overflow error,\n  due to similar reasons.\n  Future versions of ijson\n  might change the default value of this option\n  to ``True``.\n- The ``multiple_values`` option (defaults to ``False``)\n  controls whether multiple top-level values are supported.\n  JSON content should contain a single top-level value\n  (see `the JSON Grammar <https://tools.ietf.org/html/rfc7159#section-2>`_).\n  However there are plenty of JSON files out in the wild\n  that contain multiple top-level values,\n  often separated by newlines.\n  By default ijson will fail to process these\n  with a ``parse error: trailing garbage`` error\n  unless ``multiple_values=True`` is specified.\n- Similarly the ``allow_comments`` option (defaults to ``False``)\n  controls whether C-style comments (e.g., ``/* a comment */``),\n  which are not supported by the JSON standard,\n  are allowed in the content or not.\n- For functions taking a file-like object,\n  an additional ``buf_size`` option (defaults to ``65536`` or 64KB)\n  specifies the amount of bytes the library\n  should attempt to read each time.\n- The ``items`` and ``kvitems`` functions, and all their variants,\n  have an optional ``map_type`` argument (defaults to ``dict``)\n  used to construct objects from the JSON stream.\n  This should be a dict-like type supporting item assignment.\n\n\nEvents\n======\n\nWhen using the lower-level ``ijson.parse`` function,\nthree-element tuples are generated\ncontaining a prefix, an event name, and a value.\nEvents will be one of the following:\n\n- ``start_map`` and ``end_map`` indicate\n  the beginning and end of a JSON object, respectively.\n  They carry a ``None`` as their value.\n- ``start_array`` and ``end_array`` indicate\n  the beginning and end of a JSON array, respectively.\n  They also carry a ``None`` as their value.\n- ``map_key`` indicates the name of a field in a JSON object.\n  Its associated value is the name itself.\n- ``null``, ``boolean``, ``integer``, ``double``, ``number`` and ``string``\n  all indicate actual content, which is stored in the associated value.\n\n\n.. _prefix:\n\nPrefix\n======\n\nA prefix represents the context within a JSON document\nwhere an event originates at.\nIt works as follows:\n\n- It starts as an empty string.\n- A ``<name>`` part is appended when the parser starts parsing the contents\n  of a JSON object member called ``name``,\n  and removed once the content finishes.\n- A literal ``item`` part is appended when the parser is parsing\n  elements of a JSON array,\n  and removed when the array ends.\n- Parts are separated by ``.``.\n\nWhen using the ``ijson.items`` function,\nthe prefix works as the selection\nfor which objects should be automatically built and returned by ijson.\n\n\n.. _backends:\n\nBackends\n========\n\nIjson provides several implementations of the actual parsing in the form of\nbackends located in ijson/backends:\n\n- ``yajl2_c``: a C extension using `YAJL <http://lloyd.github.com/yajl/>`_ 2.x.\n  This is the fastest, but *might* require a compiler and the YAJL development files\n  to be present when installing this package.\n  Binary wheel distributions exist for major platforms/architectures to spare users\n  from having to compile the package.\n- ``yajl2_cffi``: wrapper around `YAJL <http://lloyd.github.com/yajl/>`_ 2.x\n  using CFFI.\n- ``yajl2``: wrapper around YAJL 2.x using ctypes, for when you can't use CFFI\n  for some reason.\n- ``yajl``: deprecated YAJL 1.x + ctypes wrapper, for even older systems.\n- ``python``: pure Python parser, good to use with PyPy\n\nYou can import a specific backend and use it in the same way as the top level\nlibrary:\n\n.. code-block::  python\n\n    import ijson.backends.yajl2_cffi as ijson\n\n    for item in ijson.items(...):\n        # ...\n\nImporting the top level library as ``import ijson``\nuses the first available backend in the same order of the list above,\nand its name is recorded under ``ijson.backend``.\nIf the ``IJSON_BACKEND`` environment variable is set\nits value takes precedence and is used to select the default backend.\n\nYou can also use the ``ijson.get_backend`` function\nto get a specific backend based on a name:\n\n.. code-block:: python\n\n    backend = ijson.get_backend('yajl2_c')\n    for item in backend.items(...):\n        # ...\n\n\nPerformance tips\n================\n\nIn more-or-less decreasing order,\nthese are the most common actions you can take\nto ensure you get most of the performance\nout of ijson:\n\n- Make sure you use the fastest backend available.\n  See backends_ for details.\n- If you know your JSON data\n  contains only numbers that are \"well behaved\"\n  consider turning on the ``use_float`` option.\n  See options_ for details.\n- Make sure you feed ijson with binary data\n  instead of text data.\n  See faq_ #1 for details.\n- Play with the ``buf_size`` option,\n  as depending on your data source and your system\n  a value different from the default\n  might show better performance.\n  See options_ for details.\n\n\n.. _faq:\n\nFAQ\n===\n\n#. **Q**: Does ijson work with ``bytes`` or ``str`` values?\n\n   **A**: In short: both are accepted as input, outputs are only ``str``.\n\n   All ijson functions expecting a file-like object\n   should ideally be given one\n   that is opened in binary mode\n   (i.e., its ``read`` function returns ``bytes`` objects, not ``str``).\n   However if a text-mode file object is given\n   then the library will automatically\n   encode the strings into UTF-8 bytes.\n   A warning is currently issued (but not visible by default)\n   alerting users about this automatic conversion.\n\n   On the other hand ijson always returns text data\n   (JSON string values, object member names, event names, etc)\n   as ``str`` objects in python 3,\n   and ``unicode`` objects in python 2.7.\n   This mimics the behavior of the system ``json`` module.\n\n#. **Q**: How are numbers dealt with?\n\n   **A**: ijson returns ``int`` values for integers\n   and ``decimal.Decimal`` values for floating-point numbers.\n   This is mostly because of historical reasons.\n   Since 3.1 a new ``use_float`` option (defaults to ``False``)\n   is available to return ``float`` values instead.\n   See the options_ section for details.\n\n#. **Q**: I'm getting an ``UnicodeDecodeError``, or an ``IncompleteJSONError`` with no message\n\n   **A**: This error is caused by byte sequences that are not valid in UTF-8.\n   In other words, the data given to ijson is not *really* UTF-8 encoded,\n   or at least not properly.\n\n   Depending on where the data comes from you have different options:\n\n   * If you have control over the source of the data, fix it.\n\n   * If you have a way to intercept the data flow,\n     do so and pass it through a \"byte corrector\".\n     For instance, if you have a shell pipeline\n     feeding data through ``stdin`` into your process\n     you can add something like ``... | iconv -f utf8 -t utf8 -c | ...``\n     in between to correct invalid byte sequences.\n\n   * If you are working purely in python,\n     you can create a UTF-8 decoder\n     using codecs' `incrementaldecoder <https://docs.python.org/3/library/codecs.html#codecs.getincrementaldecoder>`_\n     to leniently decode your bytes into strings,\n     and feed those strings (using a file-like class) into ijson\n     (see our `string_reader_async internal class <https://github.com/ICRAR/ijson/blob/0157f3c65a7986970030d3faa75979ee205d3806/ijson/utils35.py#L19>`_\n     for some inspiration).\n\n   In the future ijson might offer something out of the box\n   to deal with invalid UTF-8 byte sequences.\n\n#. **Q**: I'm getting ``parse error: trailing garbage`` or ``Additional data found`` errors\n\n   **A**: This error signals that the input\n   contains more data than the top-level JSON value it's meant to contain.\n   This is *usually* caused by JSON data sources\n   containing multiple values, and is *usually* solved\n   by passing the ``multiple_values=True`` to the ijson function in use.\n   See the options_ section for details.\n\n#. **Q**: Are there any differences between the backends?\n\n   **A**: Apart from their performance,\n   all backends are designed to support the same capabilities.\n   There are however some small known differences:\n\n   * The ``yajl`` backend doesn't support ``multiple_values=True``.\n     It also doesn't complain about additional data\n     found after the end of the top-level JSON object.\n     When using ``use_float=True`` it also doesn't properly support\n     values greater than 2^32 in 32-bit platforms or Windows.\n     Numbers with leading zeros are not reported as invalid\n     (although they are invalid JSON numbers).\n     Incomplete JSON tokens at the end of an incomplete document\n     (e.g., ``{\"a\": fals``) are not reported as ``IncompleteJSONError``.\n\n   * The ``python`` backend doesn't support ``allow_comments=True``\n     It also internally works with ``str`` objects, not ``bytes``,\n     but this is an internal detail that users shouldn't need to worry about,\n     and might change in the future.\n\n\nAcknowledgements\n================\n\nijson was originally developed and actively maintained until 2016\nby `Ivan Sagalaev <http://softwaremaniacs.org/>`_.\nIn 2019 he\n`handed over <https://github.com/isagalaev/ijson/pull/58#issuecomment-500596815>`_\nthe maintenance of the project and the PyPI ownership.\n\nPython parser in ijson is relatively simple thanks to `Douglas Crockford\n<http://www.crockford.com/>`_ who invented a strict, easy to parse syntax.\n\nThe `YAJL <http://lloyd.github.com/yajl/>`_ library by `Lloyd Hilaiel\n<http://lloyd.io/>`_ is the most popular and efficient way to parse JSON in an\niterative fashion.\n\nIjson was inspired by `yajl-py <http://pykler.github.com/yajl-py/>`_ wrapper by\n`Hatem Nassrat <http://www.nassrat.ca/>`_. Though ijson borrows almost nothing\nfrom the actual yajl-py code it was used as an example of integration with yajl\nusing ctypes.\n",
      "keywords": "",
      "platform": [],
      "classifiers": [
        "Development Status :: 5 - Production/Stable",
        "License :: OSI Approved :: BSD License",
        "Programming Language :: Python :: 2.7",
        "Programming Language :: Python :: 3.4",
        "Programming Language :: Python :: 3.5",
        "Programming Language :: Python :: 3.6",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Environment :: MetaData :: IBM Python Ecosystem"
      ],
      "download_url": "",
      "supported_platform": [],
      "comment": "",
      "provides": [],
      "requires": [],
      "obsoletes": [],
      "project_urls": [],
      "provides_dist": [],
      "obsoletes_dist": [],
      "requires_dist": [],
      "requires_external": [],
      "requires_python": "",
      "description_content_type": "text/x-rst",
      "provides_extras": "",
      "dynamic": "",
      "license_expression": "",
      "license_file": "",
      "+links": [
        {
          "rel": "releasefile",
          "hash_spec": "sha256=54702b93b0ef8e2c2b13c787e026756c7d16a9241b4e32bf5b51c4196ae656de",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/547/02b93b0ef8e2c/ijson-3.1.4+ppc64le1-py3-none-any.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                5
              ],
              "dst": "ppc64le/linux"
            }
          ]
        }
      ]
    },
    "3.4.0+ppc64le1": {
      "name": "ijson",
      "version": "3.4.0+ppc64le1",
      "metadata_version": "2.4",
      "summary": "Iterative JSON parser with standard Python iterator interfaces",
      "home_page": "",
      "author": "",
      "author_email": "Rodrigo Tobar <rtobar@icrar.org>, Ivan Sagalaev <maniac@softwaremaniacs.org>",
      "maintainer": "",
      "maintainer_email": "",
      "license": "",
      "description": ".. image:: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://github.com/ICRAR/ijson/actions/workflows/fast-built-and-test.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://coveralls.io/repos/github/ICRAR/ijson/badge.svg?branch=master\n    :target: https://coveralls.io/github/ICRAR/ijson?branch=master\n\n.. image:: https://badge.fury.io/py/ijson.svg\n    :target: https://badge.fury.io/py/ijson\n\n.. image:: https://img.shields.io/pypi/pyversions/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dd/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dw/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dm/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n\n=====\nijson\n=====\n\nIjson is an iterative JSON parser with standard Python iterator interfaces.\n\n.. contents::\n   :local:\n\n\nInstallation\n============\n\nIjson is hosted in PyPI, so you should be able to install it via ``pip``::\n\n  pip install ijson\n\nBinary wheels are provided\nfor major platforms\nand python versions.\nThese are built and published automatically\nusing `cibuildwheel <https://cibuildwheel.readthedocs.io/en/stable/>`_\nvia GitHub Actions.\n\n\nUsage\n=====\n\nAll usage example will be using a JSON document describing geographical\nobjects:\n\n.. code-block:: json\n\n    {\n      \"earth\": {\n        \"europe\": [\n          {\"name\": \"Paris\", \"type\": \"city\", \"info\": { ... }},\n          {\"name\": \"Thames\", \"type\": \"river\", \"info\": { ... }},\n          // ...\n        ],\n        \"america\": [\n          {\"name\": \"Texas\", \"type\": \"state\", \"info\": { ... }},\n          // ...\n        ]\n      }\n    }\n\n\nHigh-level interfaces\n---------------------\n\nMost common usage is having ijson yield native Python objects out of a JSON\nstream located under a prefix.\nThis is done using the ``items`` function.\nHere's how to process all European cities:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    objects = ijson.items(f, 'earth.europe.item')\n    cities = (o for o in objects if o['type'] == 'city')\n    for city in cities:\n        do_something_with(city)\n\nFor how to build a prefix see the prefix_ section below.\n\nOther times it might be useful to iterate over object members\nrather than objects themselves (e.g., when objects are too big).\nIn that case one can use the ``kvitems`` function instead:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    european_places = ijson.kvitems(f, 'earth.europe.item')\n    names = (v for k, v in european_places if k == 'name')\n    for name in names:\n        do_something_with(name)\n\n\nLower-level interfaces\n----------------------\n\nSometimes when dealing with a particularly large JSON payload it may worth to\nnot even construct individual Python objects and react on individual events\nimmediately producing some result.\nThis is achieved using the ``parse`` function:\n\n.. code-block::  python\n\n    import ijson\n\n    parser = ijson.parse(urlopen('http://.../'))\n    stream.write('<geo>')\n    for prefix, event, value in parser:\n        if (prefix, event) == ('earth', 'map_key'):\n            stream.write('<%s>' % value)\n            continent = value\n        elif prefix.endswith('.name'):\n            stream.write('<object name=\"%s\"/>' % value)\n        elif (prefix, event) == ('earth.%s' % continent, 'end_map'):\n            stream.write('</%s>' % continent)\n    stream.write('</geo>')\n\nEven more bare-bones is the ability to react on individual events\nwithout even calculating a prefix\nusing the ``basic_parse`` function:\n\n.. code-block:: python\n\n    import ijson\n\n    events = ijson.basic_parse(urlopen('http://.../'))\n    num_names = sum(1 for event, value in events\n                    if event == 'map_key' and value == 'name')\n\n\n.. _command_line:\n\nCommand line\n------------\n\nA command line utility is included with ijson\nto help visualise the output of each of the routines above.\nIt reads JSON from the standard input,\nand it prints the results of the parsing method chosen by the user\nto the standard output.\n\nThe tool is available by running the ``ijson.dump`` module.\nFor example::\n\n $> echo '{\"A\": 0, \"B\": [1, 2, 3, 4]}' | python -m ijson.dump -m parse\n #: path, name, value\n --------------------\n 0: , start_map, None\n 1: , map_key, A\n 2: A, number, 0\n 3: , map_key, B\n 4: B, start_array, None\n 5: B.item, number, 1\n 6: B.item, number, 2\n 7: B.item, number, 3\n 8: B.item, number, 4\n 9: B, end_array, None\n 10: , end_map, None\n\nUsing ``-h/--help`` will show all available options.\n\n\n.. _benchmarking:\n\nBenchmarking\n------------\n\nA command line utility is included with ijson\nto help benchmarking the different methods offered by the package.\nIt offers some built-in example inputs\nthat try to mimic different scenarios,\nbut more importantly it also supports user-provided inputs.\nYou can also specify which backends to time,\nnumber of iterations,\nand more.\n\nThe tool is available by running the ``ijson.benchmark`` module.\nFor example::\n\n $> python -m ijson.benchmark my/json/file.json -m items -p values.item\n\nUsing ``-h/--help`` will show all available options.\n\n\n``bytes``/``str`` support\n-------------------------\n\nAlthough not usually how they are meant to be run,\nall the functions above also accept\n``bytes`` and ``str`` objects\ndirectly as inputs.\nThese are then internally wrapped into a file object,\nand further processed.\nThis is useful for testing and prototyping,\nbut probably not extremely useful in real-life scenarios.\n\n\n``asyncio`` support\n-------------------\n\nAll of the methods above\nwork also on file-like asynchronous objects,\nso they can be iterated asynchronously.\nIn other words, something like this:\n\n.. code-block:: python\n\n   import asyncio\n   import ijson\n\n   async def run():\n      f = await async_urlopen('http://..../')\n      async for object in ijson.items(f, 'earth.europe.item'):\n         if object['type'] == 'city':\n            do_something_with(city)\n   asyncio.run(run())\n\nAn explicit set of ``*_async`` functions also exists\noffering the same functionality,\nexcept they will fail if anything other\nthan a file-like asynchronous object is given to them.\n(so the example above can also be written using ``ijson.items_async``).\nIn fact in ijson version 3.0\nthis was the only way to access\nthe ``asyncio`` support.\n\n\nIntercepting events\n-------------------\n\nThe four routines shown above\ninternally chain against each other:\ntuples generated by ``basic_parse``\nare the input for ``parse``,\nwhose results are the input to ``kvitems`` and ``items``.\n\nNormally users don't see this interaction,\nas they only care about the final output\nof the function they invoked,\nbut there are occasions when tapping\ninto this invocation chain this could be handy.\nThis is supported\nby passing the output of one function\n(i.e., an iterable of events, usually a generator)\nas the input of another,\nopening the door for user event filtering or injection.\n\nFor instance if one wants to skip some content\nbefore full item parsing:\n\n.. code-block:: python\n\n  import io\n  import ijson\n\n  parse_events = ijson.parse(io.BytesIO(b'[\"skip\", {\"a\": 1}, {\"b\": 2}, {\"c\": 3}]'))\n  while True:\n      prefix, event, value = next(parse_events)\n      if value == \"skip\":\n          break\n  for obj in ijson.items(parse_events, 'item'):\n      print(obj)\n\n\nNote that this interception\nonly makes sense for the ``basic_parse -> parse``,\n``parse -> items`` and ``parse -> kvitems`` interactions.\n\nNote also that event interception\nis currently not supported\nby the ``async`` functions.\n\n\nPush interfaces\n---------------\n\nAll examples above use a file-like object as the data input\n(both the normal case, and for ``asyncio`` support),\nand hence are \"pull\" interfaces,\nwith the library reading data as necessary.\nIf for whatever reason it's not possible to use such method,\nyou can still **push** data\nthrough yet a different interface: `coroutines <https://www.python.org/dev/peps/pep-0342/>`_\n(via generators, not ``asyncio`` coroutines).\nCoroutines effectively allow users\nto send data to them at any point in time,\nwith a final *target* coroutine-like object\nreceiving the results.\n\nIn the following example\nthe user is doing the reading\ninstead of letting the library do it:\n\n.. code-block:: python\n\n   import ijson\n\n   @ijson.coroutine\n   def print_cities():\n      while True:\n         obj = (yield)\n         if obj['type'] != 'city':\n            continue\n         print(obj)\n\n   coro = ijson.items_coro(print_cities(), 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n   coro.close()\n\nAll four ijson iterators\nhave a ``*_coro`` counterpart\nthat work by pushing data into them.\nInstead of receiving a file-like object\nand option buffer size as arguments,\nthey receive a single ``target`` argument,\nwhich should be a coroutine-like object\n(anything implementing a ``send`` method)\nthrough which results will be published.\n\nAn alternative to providing a coroutine\nis to use ``ijson.sendable_list`` to accumulate results,\nproviding the list is cleared after each parsing iteration,\nlike this:\n\n.. code-block:: python\n\n   import ijson\n\n   events = ijson.sendable_list()\n   coro = ijson.items_coro(events, 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n      process_accumulated_events(events)\n      del events[:]\n   coro.close()\n   process_accumulated_events(events)\n\n\n.. _options:\n\nOptions\n=======\n\nAdditional options are supported by **all** ijson functions\nto give users more fine-grained control over certain operations:\n\n- The ``use_float`` option (defaults to ``False``)\n  controls how non-integer values are returned to the user.\n  If set to ``True`` users receive ``float()`` values;\n  otherwise ``Decimal`` values are constructed.\n  Note that building ``float`` values is usually faster,\n  but on the other hand there might be loss of precision\n  (which most applications will not care about)\n  and will raise an exception when overflow occurs\n  (e.g., if ``1e400`` is encountered).\n  This option also has the side-effect\n  that integer numbers bigger than ``2^64``\n  (but *sometimes* ``2^32``, see capabilities_)\n  will also raise an overflow error,\n  due to similar reasons.\n  Future versions of ijson\n  might change the default value of this option\n  to ``True``.\n- The ``multiple_values`` option (defaults to ``False``)\n  controls whether multiple top-level values are supported.\n  JSON content should contain a single top-level value\n  (see `the JSON Grammar <https://tools.ietf.org/html/rfc7159#section-2>`_).\n  However there are plenty of JSON files out in the wild\n  that contain multiple top-level values,\n  often separated by newlines.\n  By default ijson will fail to process these\n  with a ``parse error: trailing garbage`` error\n  unless ``multiple_values=True`` is specified.\n- Similarly the ``allow_comments`` option (defaults to ``False``)\n  controls whether C-style comments (e.g., ``/* a comment */``),\n  which are not supported by the JSON standard,\n  are allowed in the content or not.\n- For functions taking a file-like object,\n  an additional ``buf_size`` option (defaults to ``65536`` or 64KB)\n  specifies the amount of bytes the library\n  should attempt to read each time.\n- The ``items`` and ``kvitems`` functions, and all their variants,\n  have an optional ``map_type`` argument (defaults to ``dict``)\n  used to construct objects from the JSON stream.\n  This should be a dict-like type supporting item assignment.\n\n\nEvents\n======\n\nWhen using the lower-level ``ijson.parse`` function,\nthree-element tuples are generated\ncontaining a prefix, an event name, and a value.\nEvents will be one of the following:\n\n- ``start_map`` and ``end_map`` indicate\n  the beginning and end of a JSON object, respectively.\n  They carry a ``None`` as their value.\n- ``start_array`` and ``end_array`` indicate\n  the beginning and end of a JSON array, respectively.\n  They also carry a ``None`` as their value.\n- ``map_key`` indicates the name of a field in a JSON object.\n  Its associated value is the name itself.\n- ``null``, ``boolean``, ``integer``, ``double``, ``number`` and ``string``\n  all indicate actual content, which is stored in the associated value.\n\n\n.. _prefix:\n\nPrefix\n======\n\nA prefix represents the context within a JSON document\nwhere an event originates at.\nIt works as follows:\n\n- It starts as an empty string.\n- A ``<name>`` part is appended when the parser starts parsing the contents\n  of a JSON object member called ``name``,\n  and removed once the content finishes.\n- A literal ``item`` part is appended when the parser is parsing\n  elements of a JSON array,\n  and removed when the array ends.\n- Parts are separated by ``.``.\n\nWhen using the ``ijson.items`` function,\nthe prefix works as the selection\nfor which objects should be automatically built and returned by ijson.\n\n\n.. _backends:\n\nBackends\n========\n\nIjson provides several implementations of the actual parsing in the form of\nbackends located in ijson/backends:\n\n- ``yajl2_c``: a C extension using `YAJL <http://lloyd.github.io/yajl/>`__ 2.x.\n  This is the fastest, but *might* require a compiler and the YAJL development files\n  to be present when installing this package.\n  Binary wheel distributions exist for major platforms/architectures to spare users\n  from having to compile the package.\n- ``yajl2_cffi``: wrapper around `YAJL <http://lloyd.github.io/yajl/>`__ 2.x\n  using CFFI.\n- ``yajl2``: wrapper around YAJL 2.x using ctypes, for when you can't use CFFI\n  for some reason.\n- ``yajl``: deprecated YAJL 1.x + ctypes wrapper, for even older systems.\n- ``python``: pure Python parser, good to use with PyPy\n\nThis list of backend names is available under the ``ijson.ALL_BACKENDS`` constant.\n\nYou can import a specific backend and use it in the same way as the top level\nlibrary:\n\n.. code-block::  python\n\n    import ijson.backends.yajl2_cffi as ijson\n\n    for item in ijson.items(...):\n        # ...\n\nImporting the top level library as ``import ijson``\nuses the first available backend in the same order of the list above,\nand its name is recorded under ``ijson.backend``.\nIf the ``IJSON_BACKEND`` environment variable is set\nits value takes precedence and is used to select the default backend.\n\nYou can also use the ``ijson.get_backend`` function\nto get a specific backend based on a name:\n\n.. code-block:: python\n\n    backend = ijson.get_backend('yajl2_c')\n    for item in backend.items(...):\n        # ...\n\n\n.. _capabilities:\n\nCapabilities\n------------\n\nApart from their performance,\nall backends are designed to support the same capabilities.\nThere are however some small known differences,\nall of which can be queried by inspecting\nthe ``capabilities`` module constant.\nIt contains the following members:\n\n* ``c_comments``: C-style comments are supported.\n* ``multiple_values``: multiple top-level JSON values are supported.\n* ``detects_invalid_leading_zeros``: numbers with leading zeroes\n  are reported as invalid (as they should, as pert the JSON standard),\n  raising a ``ValueError``.\n* ``detects_incomplete_json_tokens``: detects incomplete JSON tokens\n  at the end of an incomplete document (e.g., ``{\"a\": fals``),\n  raising an ``IncompleteJSONError``.\n* ``int64``: when using ``use_float=True``,\n    values greater than or equal to ``2^32`` are correctly returned.\n\nThese capabilities are supported by all backends,\nwith the following exceptions:\n\n* The ``yajl`` backend doesn't support ``multiple_values``,\n  ``detects_invalid_leading_zeros`` and ``detects_incomplete_json_tokens``.\n  It also doesn't support ``int64``\n  in platforms with a 32-bit C ``long`` type.\n\n* The ``python`` backend doesn't support ``c_comments``.\n\n\nPerformance tips\n================\n\nIn more-or-less decreasing order,\nthese are the most common actions you can take\nto ensure you get most of the performance\nout of ijson:\n\n- Make sure you use the fastest backend available.\n  See backends_ for details.\n- If you know your JSON data\n  contains only numbers that are \"well behaved\"\n  consider turning on the ``use_float`` option.\n  See options_ for details.\n- Make sure you feed ijson with binary data\n  instead of text data.\n  See faq_ #1 for details.\n- Play with the ``buf_size`` option,\n  as depending on your data source and your system\n  a value different from the default\n  might show better performance.\n  See options_ for details.\n\nThe benchmarking_ tool should help\nwith trying some of these options\nand observing their effect on your input files.\n\n\n.. _faq:\n\nFAQ\n===\n\n#. **Q**: Does ijson work with ``bytes`` or ``str`` values?\n\n   **A**: In short: both are accepted as input, outputs are only ``str``.\n\n   All ijson functions expecting a file-like object\n   should ideally be given one\n   that is opened in binary mode\n   (i.e., its ``read`` function returns ``bytes`` objects, not ``str``).\n   However if a text-mode file object is given\n   then the library will automatically\n   encode the strings into UTF-8 bytes.\n   A warning is currently issued (but not visible by default)\n   alerting users about this automatic conversion.\n\n   On the other hand ijson always returns text data\n   (JSON string values, object member names, event names, etc)\n   as ``str`` objects.\n   This mimics the behavior of the system ``json`` module.\n\n#. **Q**: How are numbers dealt with?\n\n   **A**: ijson returns ``int`` values for integers\n   and ``decimal.Decimal`` values for floating-point numbers.\n   This is mostly because of historical reasons.\n   Since 3.1 a new ``use_float`` option (defaults to ``False``)\n   is available to return ``float`` values instead.\n   See the options_ section for details.\n\n#. **Q**: I'm getting an ``UnicodeDecodeError``, or an ``IncompleteJSONError`` with no message\n\n   **A**: This error is caused by byte sequences that are not valid in UTF-8.\n   In other words, the data given to ijson is not *really* UTF-8 encoded,\n   or at least not properly.\n\n   Depending on where the data comes from you have different options:\n\n   * If you have control over the source of the data, fix it.\n\n   * If you have a way to intercept the data flow,\n     do so and pass it through a \"byte corrector\".\n     For instance, if you have a shell pipeline\n     feeding data through ``stdin`` into your process\n     you can add something like ``... | iconv -f utf8 -t utf8 -c | ...``\n     in between to correct invalid byte sequences.\n\n   * If you are working purely in python,\n     you can create a UTF-8 decoder\n     using codecs' `incrementaldecoder <https://docs.python.org/3/library/codecs.html#codecs.getincrementaldecoder>`_\n     to leniently decode your bytes into strings,\n     and feed those strings (using a file-like class) into ijson\n     (see our `string_reader_async internal class <https://github.com/ICRAR/ijson/blob/0157f3c65a7986970030d3faa75979ee205d3806/ijson/utils35.py#L19>`_\n     for some inspiration).\n\n   In the future ijson might offer something out of the box\n   to deal with invalid UTF-8 byte sequences.\n\n#. **Q**: I'm getting ``parse error: trailing garbage`` or ``Additional data found`` errors\n\n   **A**: This error signals that the input\n   contains more data than the top-level JSON value it's meant to contain.\n   This is *usually* caused by JSON data sources\n   containing multiple values, and is *usually* solved\n   by passing the ``multiple_values=True`` to the ijson function in use.\n   See the options_ section for details.\n\n\nAcknowledgements\n================\n\nijson was originally developed and actively maintained until 2016\nby `Ivan Sagalaev <http://softwaremaniacs.org/>`_.\nIn 2019 he\n`handed over <https://github.com/isagalaev/ijson/pull/58#issuecomment-500596815>`_\nthe maintenance of the project and the PyPI ownership.\n\nPython parser in ijson is relatively simple thanks to `Douglas Crockford\n<http://www.crockford.com/>`_ who invented a strict, easy to parse syntax.\n\nThe `YAJL <https://lloyd.github.io/yajl>`__ library by `Lloyd Hilaiel\n<http://lloyd.io/>`_ is the most popular and efficient way to parse JSON in an\niterative fashion.\nWhen building the library ourselves,\nwe use `our own fork <https://github.com/rtobar/yajl>`__\nthat contains fixes for all known CVEs.\n\nIjson was inspired by `yajl-py <http://pykler.github.com/yajl-py/>`_ wrapper by\n`Hatem Nassrat <http://www.nassrat.ca/>`_. Though ijson borrows almost nothing\nfrom the actual yajl-py code it was used as an example of integration with yajl\nusing ctypes.\n",
      "keywords": "",
      "platform": [],
      "classifiers": [
        "Development Status :: 5 - Production/Stable",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Programming Language :: Python :: 3.13",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Environment :: MetaData :: IBM Python Ecosystem"
      ],
      "download_url": "",
      "supported_platform": [],
      "comment": "",
      "provides": [],
      "requires": [],
      "obsoletes": [],
      "project_urls": [
        "Homepage, https://github.com/ICRAR/ijson"
      ],
      "provides_dist": [],
      "obsoletes_dist": [],
      "requires_dist": [],
      "requires_external": [],
      "requires_python": ">=3.9",
      "description_content_type": "text/x-rst",
      "provides_extras": "",
      "dynamic": "license-file",
      "license_expression": "BSD-3-Clause AND ISC",
      "license_file": "LICENSE.txt",
      "+links": [
        {
          "rel": "releasefile",
          "hash_spec": "sha256=f30beb0abb13d07893aeee2941c1a5447c867c6b00a3c3573695331e41234b7f",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/f30/beb0abb13d078/ijson-3.4.0+ppc64le1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                9
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=668c9860e02fd9b4b195658bae178b40a7b16a568d861442f3b39b9f7a6c4dd6",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/668/c9860e02fd9b4/ijson-3.4.0+ppc64le1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                9
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=91d1350bc562e71f7be5bff1d18760652d3617e9f3e36e12371f8852679f5641",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/91d/1350bc562e71f/ijson-3.4.0+ppc64le1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                9
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=56dd27558cdcf58285edd48807da787c54a8256d4061598442b73fecd704938c",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/56d/d27558cdcf582/ijson-3.4.0+ppc64le1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                10
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=7f7dc7469f7bc5f2a43715de116e7671d8294f350281f25f57247dc55c2abfdc",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/7f7/dc7469f7bc5f2/ijson-3.4.0+ppc64le1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                10
              ],
              "dst": "ppc64le/linux"
            }
          ]
        }
      ]
    },
    "3.5.1": {
      "name": "ijson",
      "version": "3.5.1",
      "metadata_version": "2.4",
      "summary": "Iterative JSON parser with standard Python iterator interfaces",
      "home_page": "",
      "author": "",
      "author_email": "Rodrigo Tobar <rtobar@icrar.org>, Ivan Sagalaev <maniac@softwaremaniacs.org>",
      "maintainer": "",
      "maintainer_email": "",
      "license": "",
      "description": ".. image:: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://github.com/ICRAR/ijson/actions/workflows/fast-built-and-test.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://coveralls.io/repos/github/ICRAR/ijson/badge.svg?branch=master\n    :target: https://coveralls.io/github/ICRAR/ijson?branch=master\n\n.. image:: https://badge.fury.io/py/ijson.svg\n    :target: https://badge.fury.io/py/ijson\n\n.. image:: https://img.shields.io/pypi/pyversions/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dd/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dw/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dm/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n\n=====\nijson\n=====\n\nIjson is an iterative JSON parser with standard Python iterator interfaces.\n\n.. contents::\n   :local:\n\n\nInstallation\n============\n\nIjson is hosted in PyPI, so you should be able to install it via ``pip``::\n\n  pip install ijson\n\nBinary wheels are provided\nfor major platforms\nand python versions.\nThese are built and published automatically\nusing `cibuildwheel <https://cibuildwheel.readthedocs.io/en/stable/>`_\nvia GitHub Actions.\n\n\nUsage\n=====\n\nAll usage example will be using a JSON document describing geographical\nobjects:\n\n.. code-block:: json\n\n    {\n      \"earth\": {\n        \"europe\": [\n          {\"name\": \"Paris\", \"type\": \"city\", \"info\": { ... }},\n          {\"name\": \"Thames\", \"type\": \"river\", \"info\": { ... }},\n          // ...\n        ],\n        \"america\": [\n          {\"name\": \"Texas\", \"type\": \"state\", \"info\": { ... }},\n          // ...\n        ]\n      }\n    }\n\n\nHigh-level interfaces\n---------------------\n\nijson works by continuously reading data from a JSON stream provided by the user.\nThis is presented as a file-like object.\nIn particular it must provide a ``read(size)`` method\nreturning either ``bytes`` (preferably) or ``str``.\nExample file-like objects are\nfiles opened with ``open``,\nHTTP/HTTPS requests made using ``urllib.request.urlopen``,\n``socket.socket`` objects,\nand more.\n\nThe most common usage of ijson is to yield native Python objects\nlocated under a prefix.\nThis is done using the ``items`` function.\nHere's how to process all European cities:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    objects = ijson.items(f, 'earth.europe.item')\n    cities = (o for o in objects if o['type'] == 'city')\n    for city in cities:\n        do_something_with(city)\n\nFor how to build a prefix see the prefix_ section below.\n\nOther times it might be useful to iterate over object members\nrather than objects themselves (e.g., when objects are too big).\nIn that case one can use the ``kvitems`` function instead:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    european_places = ijson.kvitems(f, 'earth.europe.item')\n    names = (v for k, v in european_places if k == 'name')\n    for name in names:\n        do_something_with(name)\n\n\nLower-level interfaces\n----------------------\n\nSometimes when dealing with a particularly large JSON payload it may worth to\nnot even construct individual Python objects and react on individual events\nimmediately producing some result.\nThis is achieved using the ``parse`` function:\n\n.. code-block::  python\n\n    import ijson\n\n    parser = ijson.parse(urlopen('http://.../'))\n    stream.write('<geo>')\n    for prefix, event, value in parser:\n        if (prefix, event) == ('earth', 'map_key'):\n            stream.write('<%s>' % value)\n            continent = value\n        elif prefix.endswith('.name'):\n            stream.write('<object name=\"%s\"/>' % value)\n        elif (prefix, event) == ('earth.%s' % continent, 'end_map'):\n            stream.write('</%s>' % continent)\n    stream.write('</geo>')\n\nEven more bare-bones is the ability to react on individual events\nwithout even calculating a prefix\nusing the ``basic_parse`` function:\n\n.. code-block:: python\n\n    import ijson\n\n    events = ijson.basic_parse(urlopen('http://.../'))\n    num_names = sum(1 for event, value in events\n                    if event == 'map_key' and value == 'name')\n\n\nCommand line\n------------\n\nA command line utility is included with ijson\nto help visualise the output of each of the routines above.\nIt reads JSON from the standard input,\nand it prints the results of the parsing method chosen by the user\nto the standard output.\n\nThe tool is available by running the ``ijson.dump`` module.\nFor example::\n\n $> echo '{\"A\": 0, \"B\": [1, 2, 3, 4]}' | python -m ijson.dump -m parse\n #: path, name, value\n --------------------\n 0: , start_map, None\n 1: , map_key, A\n 2: A, number, 0\n 3: , map_key, B\n 4: B, start_array, None\n 5: B.item, number, 1\n 6: B.item, number, 2\n 7: B.item, number, 3\n 8: B.item, number, 4\n 9: B, end_array, None\n 10: , end_map, None\n\nUsing ``-h/--help`` will show all available options.\n\n\nBenchmarking\n------------\n\nA command line utility is included with ijson\nto help benchmarking the different methods offered by the package.\nIt offers some built-in example inputs\nthat try to mimic different scenarios,\nbut more importantly it also supports user-provided inputs.\nYou can also specify which backends to time,\nnumber of iterations,\nand more.\n\nThe tool is available by running the ``ijson.benchmark`` module.\nFor example::\n\n $> python -m ijson.benchmark my/json/file.json -m items -p values.item\n\nUsing ``-h/--help`` will show all available options.\n\n\n``bytes``/``str`` support\n-------------------------\n\nAlthough not usually how they are meant to be run,\nall the functions above also accept\n``bytes`` and ``str`` objects\ndirectly as inputs.\nThese are then internally wrapped into a file object,\nand further processed.\nThis is useful for testing and prototyping,\nbut probably not extremely useful in real-life scenarios.\n\n\nIterator support\n----------------\n\nIn many situations the direct input users want to pass to ijson\nis an iterator (e.g., a generator) rather than a file-like object.\nijson provides a built-in adapter to bridge this gap:\n\n- ``ijson.from_iter(iterable_or_async_iterable_of_bytes)``\n\n\n``asyncio`` support\n-------------------\n\nAll of the methods above\nwork also on file-like asynchronous objects,\nso they can be iterated asynchronously.\nIn other words, something like this:\n\n.. code-block:: python\n\n   import asyncio\n   import ijson\n\n   async def run():\n      f = await async_urlopen('http://..../')\n      async for object in ijson.items(f, 'earth.europe.item'):\n         if object['type'] == 'city':\n            do_something_with(city)\n   asyncio.run(run())\n\nAn explicit set of ``*_async`` functions also exists\noffering the same functionality,\nexcept they will fail if anything other\nthan a file-like asynchronous object is given to them.\n(so the example above can also be written using ``ijson.items_async``).\nIn fact in ijson version 3.0\nthis was the only way to access\nthe ``asyncio`` support.\n\n\nIntercepting events\n-------------------\n\nThe four routines shown above\ninternally chain against each other:\ntuples generated by ``basic_parse``\nare the input for ``parse``,\nwhose results are the input to ``kvitems`` and ``items``.\n\nNormally users don't see this interaction,\nas they only care about the final output\nof the function they invoked,\nbut there are occasions when tapping\ninto this invocation chain this could be handy.\nThis is supported\nby passing the output of one function\n(i.e., an iterable of events, usually a generator)\nas the input of another,\nopening the door for user event filtering or injection.\n\nFor instance if one wants to skip some content\nbefore full item parsing:\n\n.. code-block:: python\n\n  import io\n  import ijson\n\n  parse_events = ijson.parse(io.BytesIO(b'[\"skip\", {\"a\": 1}, {\"b\": 2}, {\"c\": 3}]'))\n  while True:\n      prefix, event, value = next(parse_events)\n      if value == \"skip\":\n          break\n  for obj in ijson.items(parse_events, 'item'):\n      print(obj)\n\n\nNote that this interception\nonly makes sense for the ``basic_parse -> parse``,\n``parse -> items`` and ``parse -> kvitems`` interactions.\n\nNote also that event interception\nis currently not supported\nby the ``async`` functions.\n\n\nPush interfaces\n---------------\n\nAll examples above use a file-like object as the data input\n(both the normal case, and for ``asyncio`` support),\nand hence are \"pull\" interfaces,\nwith the library reading data as necessary.\nIf for whatever reason it's not possible to use such method,\nyou can still **push** data\nthrough yet a different interface: `coroutines <https://www.python.org/dev/peps/pep-0342/>`_\n(via generators, not ``asyncio`` coroutines).\nCoroutines effectively allow users\nto send data to them at any point in time,\nwith a final *target* coroutine-like object\nreceiving the results.\n\nIn the following example\nthe user is doing the reading\ninstead of letting the library do it:\n\n.. code-block:: python\n\n   import ijson\n\n   @ijson.coroutine\n   def print_cities():\n      while True:\n         obj = (yield)\n         if obj['type'] != 'city':\n            continue\n         print(obj)\n\n   coro = ijson.items_coro(print_cities(), 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n   coro.close()\n\nAll four ijson iterators\nhave a ``*_coro`` counterpart\nthat work by pushing data into them.\nInstead of receiving a file-like object\nand option buffer size as arguments,\nthey receive a single ``target`` argument,\nwhich should be a coroutine-like object\n(anything implementing a ``send`` method)\nthrough which results will be published.\n\nAn alternative to providing a coroutine\nis to use ``ijson.sendable_list`` to accumulate results,\nproviding the list is cleared after each parsing iteration,\nlike this:\n\n.. code-block:: python\n\n   import ijson\n\n   events = ijson.sendable_list()\n   coro = ijson.items_coro(events, 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n      process_accumulated_events(events)\n      del events[:]\n   coro.close()\n   process_accumulated_events(events)\n\n\nOptions\n=======\n\nAdditional options are supported by **all** ijson functions\nto give users more fine-grained control over certain operations:\n\n- The ``use_float`` option (defaults to ``False``)\n  controls how non-integer values are returned to the user.\n  If set to ``True`` users receive ``float()`` values;\n  otherwise ``Decimal`` values are constructed.\n  Note that building ``float`` values is usually faster,\n  but on the other hand there might be loss of precision\n  (which most applications will not care about)\n  and will raise an exception when overflow occurs\n  (e.g., if ``1e400`` is encountered).\n  This option also has the side-effect\n  that integer numbers bigger than ``2^64``\n  (but *sometimes* ``2^32``, see capabilities_)\n  will also raise an overflow error,\n  due to similar reasons.\n  Future versions of ijson\n  might change the default value of this option\n  to ``True``.\n- The ``multiple_values`` option (defaults to ``False``)\n  controls whether multiple top-level values are supported.\n  JSON content should contain a single top-level value\n  (see `the JSON Grammar <https://tools.ietf.org/html/rfc7159#section-2>`_).\n  However there are plenty of JSON files out in the wild\n  that contain multiple top-level values,\n  often separated by newlines.\n  By default ijson will fail to process these\n  with a ``parse error: trailing garbage`` error\n  unless ``multiple_values=True`` is specified.\n- Similarly the ``allow_comments`` option (defaults to ``False``)\n  controls whether C-style comments (e.g., ``/* a comment */``),\n  which are not supported by the JSON standard,\n  are allowed in the content or not.\n- For functions taking a file-like object,\n  an additional ``buf_size`` option (defaults to ``65536`` or 64KB)\n  specifies the amount of bytes the library\n  should attempt to read each time.\n- The ``items`` and ``kvitems`` functions, and all their variants,\n  have an optional ``map_type`` argument (defaults to ``dict``)\n  used to construct objects from the JSON stream.\n  This should be a dict-like type supporting item assignment.\n\n\nEvents\n======\n\nWhen using the lower-level ``ijson.parse`` function,\nthree-element tuples are generated\ncontaining a prefix, an event name, and a value.\nEvents will be one of the following:\n\n- ``start_map`` and ``end_map`` indicate\n  the beginning and end of a JSON object, respectively.\n  They carry a ``None`` as their value.\n- ``start_array`` and ``end_array`` indicate\n  the beginning and end of a JSON array, respectively.\n  They also carry a ``None`` as their value.\n- ``map_key`` indicates the name of a field in a JSON object.\n  Its associated value is the name itself.\n- ``null``, ``boolean``, ``integer``, ``double``, ``number`` and ``string``\n  all indicate actual content, which is stored in the associated value.\n\n\nPrefix\n======\n\nA prefix represents the context within a JSON document\nwhere an event originates at.\nIt works as follows:\n\n- It starts as an empty string.\n- A ``<name>`` part is appended when the parser starts parsing the contents\n  of a JSON object member called ``name``,\n  and removed once the content finishes.\n- A literal ``item`` part is appended when the parser is parsing\n  elements of a JSON array,\n  and removed when the array ends.\n- Parts are separated by ``.``.\n\nWhen using the ``ijson.items`` function,\nthe prefix works as the selection\nfor which objects should be automatically built and returned by ijson.\n\n\nBackends\n========\n\nIjson provides several implementations of the actual parsing in the form of\nbackends located in ijson/backends:\n\n- ``yajl2_c``: a C extension using `YAJL <http://lloyd.github.io/yajl/>`__ 2.x.\n  This is the fastest, but *might* require a compiler and the YAJL development files\n  to be present when installing this package.\n  Binary wheel distributions exist for major platforms/architectures to spare users\n  from having to compile the package.\n- ``yajl2_cffi``: wrapper around `YAJL <http://lloyd.github.io/yajl/>`__ 2.x\n  using CFFI.\n- ``yajl2``: wrapper around YAJL 2.x using ctypes, for when you can't use CFFI\n  for some reason.\n- ``yajl``: deprecated YAJL 1.x + ctypes wrapper, for even older systems.\n- ``python``: pure Python parser, good to use with PyPy\n\nThis list of backend names is available under the ``ijson.ALL_BACKENDS`` constant.\n\nYou can import a specific backend and use it in the same way as the top level\nlibrary:\n\n.. code-block::  python\n\n    import ijson.backends.yajl2_cffi as ijson\n\n    for item in ijson.items(...):\n        # ...\n\nImporting the top level library as ``import ijson``\nuses the first available backend in the same order of the list above,\nand its name is recorded under ``ijson.backend``.\nIf the ``IJSON_BACKEND`` environment variable is set\nits value takes precedence and is used to select the default backend.\n\nYou can also use the ``ijson.get_backend`` function\nto get a specific backend based on a name:\n\n.. code-block:: python\n\n    backend = ijson.get_backend('yajl2_c')\n    for item in backend.items(...):\n        # ...\n\n\nCapabilities\n------------\n\nApart from their performance,\nall backends are designed to support the same capabilities.\nThere are however some small known differences,\nall of which can be queried by inspecting\nthe ``capabilities`` module constant.\nIt contains the following members:\n\n* ``c_comments``: C-style comments are supported.\n* ``multiple_values``: multiple top-level JSON values are supported.\n* ``detects_invalid_leading_zeros``: numbers with leading zeroes\n  are reported as invalid (as they should, as pert the JSON standard),\n  raising a ``ValueError``.\n* ``detects_incomplete_json_tokens``: detects incomplete JSON tokens\n  at the end of an incomplete document (e.g., ``{\"a\": fals``),\n  raising an ``IncompleteJSONError``.\n* ``int64``: when using ``use_float=True``,\n    values greater than or equal to ``2^32`` are correctly returned.\n\nThese capabilities are supported by all backends,\nwith the following exceptions:\n\n* The ``yajl`` backend doesn't support ``multiple_values``,\n  ``detects_invalid_leading_zeros`` and ``detects_incomplete_json_tokens``.\n  It also doesn't support ``int64``\n  in platforms with a 32-bit C ``long`` type.\n\n* The ``python`` backend doesn't support ``c_comments``.\n\n\nPerformance tips\n================\n\nIn more-or-less decreasing order,\nthese are the most common actions you can take\nto ensure you get most of the performance\nout of ijson:\n\n- Make sure you use the fastest backend available.\n  See backends_ for details.\n- If you know your JSON data\n  contains only numbers that are \"well behaved\"\n  consider turning on the ``use_float`` option.\n  See options_ for details.\n- Make sure you feed ijson with binary data\n  instead of text data.\n  See faq_ #1 for details.\n- Play with the ``buf_size`` option,\n  as depending on your data source and your system\n  a value different from the default\n  might show better performance.\n  See options_ for details.\n\nThe benchmarking_ tool should help\nwith trying some of these options\nand observing their effect on your input files.\n\n\nFAQ\n===\n\n#. **Q**: Does ijson work with ``bytes`` or ``str`` values?\n\n   **A**: In short: both are accepted as input, outputs are only ``str``.\n\n   All ijson functions expecting a file-like object\n   should ideally be given one\n   that is opened in binary mode\n   (i.e., its ``read`` function returns ``bytes`` objects, not ``str``).\n   However if a text-mode file object is given\n   then the library will automatically\n   encode the strings into UTF-8 bytes.\n   A warning is currently issued (but not visible by default)\n   alerting users about this automatic conversion.\n\n   On the other hand ijson always returns text data\n   (JSON string values, object member names, event names, etc)\n   as ``str`` objects.\n   This mimics the behavior of the system ``json`` module.\n\n#. **Q**: How are numbers dealt with?\n\n   **A**: ijson returns ``int`` values for integers\n   and ``decimal.Decimal`` values for floating-point numbers.\n   This is mostly because of historical reasons.\n   Since 3.1 a new ``use_float`` option (defaults to ``False``)\n   is available to return ``float`` values instead.\n   See the options_ section for details.\n\n#. **Q**: I'm getting an ``UnicodeDecodeError``, or an ``IncompleteJSONError`` with no message\n\n   **A**: This error is caused by byte sequences that are not valid in UTF-8.\n   In other words, the data given to ijson is not *really* UTF-8 encoded,\n   or at least not properly.\n\n   Depending on where the data comes from you have different options:\n\n   * If you have control over the source of the data, fix it.\n\n   * If you have a way to intercept the data flow,\n     do so and pass it through a \"byte corrector\".\n     For instance, if you have a shell pipeline\n     feeding data through ``stdin`` into your process\n     you can add something like ``... | iconv -f utf8 -t utf8 -c | ...``\n     in between to correct invalid byte sequences.\n\n   * If you are working purely in python,\n     you can create a UTF-8 decoder\n     using codecs' `incrementaldecoder <https://docs.python.org/3/library/codecs.html#codecs.getincrementaldecoder>`_\n     to leniently decode your bytes into strings,\n     and feed those strings (using a file-like class) into ijson\n     (see our `string_reader_async internal class <https://github.com/ICRAR/ijson/blob/0157f3c65a7986970030d3faa75979ee205d3806/ijson/utils35.py#L19>`_\n     for some inspiration).\n\n   In the future ijson might offer something out of the box\n   to deal with invalid UTF-8 byte sequences.\n\n#. **Q**: I'm getting ``parse error: trailing garbage`` or ``Additional data found`` errors\n\n   **A**: This error signals that the input\n   contains more data than the top-level JSON value it's meant to contain.\n   This is *usually* caused by JSON data sources\n   containing multiple values, and is *usually* solved\n   by passing the ``multiple_values=True`` to the ijson function in use.\n   See the options_ section for details.\n\n#. **Q**: How do I use ijson with ``requests`` or ``httpx``\n\n   **A**: The ``requests`` library downloads the body of the HTTP response immediately by default.\n   To stream JSON into ijson, pass ``stream=True`` and adapt the byte iterator:\n\n   .. code-block:: python\n\n      import requests\n      import ijson\n\n      with requests.get('https://..', stream=True) as resp:\n          resp.raise_for_status()\n          f = ijson.from_iter(resp.iter_content(chunk_size=64*1024))\n          objects = ijson.items(f, 'earth.europe.item')\n          cities = (o for o in objects if o['type'] == 'city')\n          for city in cities:\n            do_something_with(city)\n\n   You can also pass ``Response.raw`` directly (it's a file-like object),\n   but using ``iter_content`` is preferred because ``requests`` will transparently\n   handle HTTP transfer encodings (e.g., gzip, chunked).\n\n\n   For async usage with ``httpx``:\n\n   .. code-block:: python\n\n      import httpx\n      import ijson\n\n      async with httpx.AsyncClient() as client:\n          async with client.stream('GET', 'https://..') as resp:\n              resp.raise_for_status()\n              f = ijson.from_iter(resp.aiter_bytes())\n              objects = ijson.items(f, 'earth.europe.item')\n              cities = (o async for o in objects if o['type'] == 'city')\n              async for city in cities:\n                do_something_with(city)\n\n\nAcknowledgements\n================\n\nijson was originally developed and actively maintained until 2016\nby `Ivan Sagalaev <http://softwaremaniacs.org/>`_.\nIn 2019 he\n`handed over <https://github.com/isagalaev/ijson/pull/58#issuecomment-500596815>`_\nthe maintenance of the project and the PyPI ownership.\n\nPython parser in ijson is relatively simple thanks to `Douglas Crockford\n<http://www.crockford.com/>`_ who invented a strict, easy to parse syntax.\n\nThe `YAJL <https://lloyd.github.io/yajl>`__ library by `Lloyd Hilaiel\n<http://lloyd.io/>`_ is the most popular and efficient way to parse JSON in an\niterative fashion.\nWhen building the library ourselves,\nwe use `our own fork <https://github.com/rtobar/yajl>`__\nthat contains fixes for all known CVEs.\n\nIjson was inspired by `yajl-py <http://pykler.github.com/yajl-py/>`_ wrapper by\n`Hatem Nassrat <http://www.nassrat.ca/>`_. Though ijson borrows almost nothing\nfrom the actual yajl-py code it was used as an example of integration with yajl\nusing ctypes.\n",
      "keywords": "",
      "platform": [],
      "classifiers": [
        "Development Status :: 5 - Production/Stable",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Programming Language :: Python :: 3.13",
        "Programming Language :: Python :: 3.14",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Environment :: MetaData :: IBM Python Ecosystem"
      ],
      "download_url": "",
      "supported_platform": [],
      "comment": "",
      "provides": [],
      "requires": [],
      "obsoletes": [],
      "project_urls": [
        "Homepage, https://github.com/ICRAR/ijson"
      ],
      "provides_dist": [],
      "obsoletes_dist": [],
      "requires_dist": [],
      "requires_external": [],
      "requires_python": ">=3.9",
      "description_content_type": "text/x-rst",
      "provides_extras": [],
      "dynamic": [
        "license-file"
      ],
      "license_expression": "BSD-3-Clause AND ISC",
      "license_file": [
        "LICENSE.txt"
      ],
      "+links": [
        {
          "rel": "releasefile",
          "hash_spec": "sha256=18f2d34b254f8eaebc4d72c110657149a365eb1639a29fbe0a8596c4b7039441",
          "hashes": {
            "sha256": "18f2d34b254f8eaebc4d72c110657149a365eb1639a29fbe0a8596c4b7039441"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/18f/2d34b254f8eae/ijson-3.5.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_34_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                9,
                17,
                8,
                9,
                46
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=6ffdb8ddee7ca60d0ac8b6c0bb08aedfcb5584ff1fb0eb603b4fbd8ed68dfe84",
          "hashes": {
            "sha256": "6ffdb8ddee7ca60d0ac8b6c0bb08aedfcb5584ff1fb0eb603b4fbd8ed68dfe84"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/6ff/db8ddee7ca60d/ijson-3.5.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_34_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                9,
                17,
                8,
                9,
                47
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=ee2ff9757abcab36099e6c21f68eb432fa6c19a17116240c87fc43a0d2127fcf",
          "hashes": {
            "sha256": "ee2ff9757abcab36099e6c21f68eb432fa6c19a17116240c87fc43a0d2127fcf"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/ee2/ff9757abcab36/ijson-3.5.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_34_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                9,
                17,
                8,
                9,
                48
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=c6fba733a96cdc96fff034d79b3fd4896c5c0dd403f22695653baf5b77fe20d2",
          "hashes": {
            "sha256": "c6fba733a96cdc96fff034d79b3fd4896c5c0dd403f22695653baf5b77fe20d2"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/c6f/ba733a96cdc96/ijson-3.5.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_34_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                9,
                17,
                8,
                9,
                49
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=2dc6ddb5df56e4bbd5a1afd543fd172badc18e1a98a3c094d19dfa530deccebf",
          "hashes": {
            "sha256": "2dc6ddb5df56e4bbd5a1afd543fd172badc18e1a98a3c094d19dfa530deccebf"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/2dc/6ddb5df56e4bb/ijson-3.5.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_34_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                9,
                17,
                8,
                9,
                49
              ],
              "dst": "ppc64le/linux"
            }
          ]
        }
      ]
    },
    "3.4.0": {
      "name": "ijson",
      "version": "3.4.0",
      "metadata_version": "2.4",
      "summary": "Iterative JSON parser with standard Python iterator interfaces",
      "home_page": "",
      "author": "",
      "author_email": "Rodrigo Tobar <rtobar@icrar.org>, Ivan Sagalaev <maniac@softwaremaniacs.org>",
      "maintainer": "",
      "maintainer_email": "",
      "license": "",
      "description": ".. image:: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://github.com/ICRAR/ijson/actions/workflows/fast-built-and-test.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://coveralls.io/repos/github/ICRAR/ijson/badge.svg?branch=master\n    :target: https://coveralls.io/github/ICRAR/ijson?branch=master\n\n.. image:: https://badge.fury.io/py/ijson.svg\n    :target: https://badge.fury.io/py/ijson\n\n.. image:: https://img.shields.io/pypi/pyversions/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dd/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dw/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dm/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n\n=====\nijson\n=====\n\nIjson is an iterative JSON parser with standard Python iterator interfaces.\n\n.. contents::\n   :local:\n\n\nInstallation\n============\n\nIjson is hosted in PyPI, so you should be able to install it via ``pip``::\n\n  pip install ijson\n\nBinary wheels are provided\nfor major platforms\nand python versions.\nThese are built and published automatically\nusing `cibuildwheel <https://cibuildwheel.readthedocs.io/en/stable/>`_\nvia GitHub Actions.\n\n\nUsage\n=====\n\nAll usage example will be using a JSON document describing geographical\nobjects:\n\n.. code-block:: json\n\n    {\n      \"earth\": {\n        \"europe\": [\n          {\"name\": \"Paris\", \"type\": \"city\", \"info\": { ... }},\n          {\"name\": \"Thames\", \"type\": \"river\", \"info\": { ... }},\n          // ...\n        ],\n        \"america\": [\n          {\"name\": \"Texas\", \"type\": \"state\", \"info\": { ... }},\n          // ...\n        ]\n      }\n    }\n\n\nHigh-level interfaces\n---------------------\n\nMost common usage is having ijson yield native Python objects out of a JSON\nstream located under a prefix.\nThis is done using the ``items`` function.\nHere's how to process all European cities:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    objects = ijson.items(f, 'earth.europe.item')\n    cities = (o for o in objects if o['type'] == 'city')\n    for city in cities:\n        do_something_with(city)\n\nFor how to build a prefix see the prefix_ section below.\n\nOther times it might be useful to iterate over object members\nrather than objects themselves (e.g., when objects are too big).\nIn that case one can use the ``kvitems`` function instead:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    european_places = ijson.kvitems(f, 'earth.europe.item')\n    names = (v for k, v in european_places if k == 'name')\n    for name in names:\n        do_something_with(name)\n\n\nLower-level interfaces\n----------------------\n\nSometimes when dealing with a particularly large JSON payload it may worth to\nnot even construct individual Python objects and react on individual events\nimmediately producing some result.\nThis is achieved using the ``parse`` function:\n\n.. code-block::  python\n\n    import ijson\n\n    parser = ijson.parse(urlopen('http://.../'))\n    stream.write('<geo>')\n    for prefix, event, value in parser:\n        if (prefix, event) == ('earth', 'map_key'):\n            stream.write('<%s>' % value)\n            continent = value\n        elif prefix.endswith('.name'):\n            stream.write('<object name=\"%s\"/>' % value)\n        elif (prefix, event) == ('earth.%s' % continent, 'end_map'):\n            stream.write('</%s>' % continent)\n    stream.write('</geo>')\n\nEven more bare-bones is the ability to react on individual events\nwithout even calculating a prefix\nusing the ``basic_parse`` function:\n\n.. code-block:: python\n\n    import ijson\n\n    events = ijson.basic_parse(urlopen('http://.../'))\n    num_names = sum(1 for event, value in events\n                    if event == 'map_key' and value == 'name')\n\n\n.. _command_line:\n\nCommand line\n------------\n\nA command line utility is included with ijson\nto help visualise the output of each of the routines above.\nIt reads JSON from the standard input,\nand it prints the results of the parsing method chosen by the user\nto the standard output.\n\nThe tool is available by running the ``ijson.dump`` module.\nFor example::\n\n $> echo '{\"A\": 0, \"B\": [1, 2, 3, 4]}' | python -m ijson.dump -m parse\n #: path, name, value\n --------------------\n 0: , start_map, None\n 1: , map_key, A\n 2: A, number, 0\n 3: , map_key, B\n 4: B, start_array, None\n 5: B.item, number, 1\n 6: B.item, number, 2\n 7: B.item, number, 3\n 8: B.item, number, 4\n 9: B, end_array, None\n 10: , end_map, None\n\nUsing ``-h/--help`` will show all available options.\n\n\n.. _benchmarking:\n\nBenchmarking\n------------\n\nA command line utility is included with ijson\nto help benchmarking the different methods offered by the package.\nIt offers some built-in example inputs\nthat try to mimic different scenarios,\nbut more importantly it also supports user-provided inputs.\nYou can also specify which backends to time,\nnumber of iterations,\nand more.\n\nThe tool is available by running the ``ijson.benchmark`` module.\nFor example::\n\n $> python -m ijson.benchmark my/json/file.json -m items -p values.item\n\nUsing ``-h/--help`` will show all available options.\n\n\n``bytes``/``str`` support\n-------------------------\n\nAlthough not usually how they are meant to be run,\nall the functions above also accept\n``bytes`` and ``str`` objects\ndirectly as inputs.\nThese are then internally wrapped into a file object,\nand further processed.\nThis is useful for testing and prototyping,\nbut probably not extremely useful in real-life scenarios.\n\n\n``asyncio`` support\n-------------------\n\nAll of the methods above\nwork also on file-like asynchronous objects,\nso they can be iterated asynchronously.\nIn other words, something like this:\n\n.. code-block:: python\n\n   import asyncio\n   import ijson\n\n   async def run():\n      f = await async_urlopen('http://..../')\n      async for object in ijson.items(f, 'earth.europe.item'):\n         if object['type'] == 'city':\n            do_something_with(city)\n   asyncio.run(run())\n\nAn explicit set of ``*_async`` functions also exists\noffering the same functionality,\nexcept they will fail if anything other\nthan a file-like asynchronous object is given to them.\n(so the example above can also be written using ``ijson.items_async``).\nIn fact in ijson version 3.0\nthis was the only way to access\nthe ``asyncio`` support.\n\n\nIntercepting events\n-------------------\n\nThe four routines shown above\ninternally chain against each other:\ntuples generated by ``basic_parse``\nare the input for ``parse``,\nwhose results are the input to ``kvitems`` and ``items``.\n\nNormally users don't see this interaction,\nas they only care about the final output\nof the function they invoked,\nbut there are occasions when tapping\ninto this invocation chain this could be handy.\nThis is supported\nby passing the output of one function\n(i.e., an iterable of events, usually a generator)\nas the input of another,\nopening the door for user event filtering or injection.\n\nFor instance if one wants to skip some content\nbefore full item parsing:\n\n.. code-block:: python\n\n  import io\n  import ijson\n\n  parse_events = ijson.parse(io.BytesIO(b'[\"skip\", {\"a\": 1}, {\"b\": 2}, {\"c\": 3}]'))\n  while True:\n      prefix, event, value = next(parse_events)\n      if value == \"skip\":\n          break\n  for obj in ijson.items(parse_events, 'item'):\n      print(obj)\n\n\nNote that this interception\nonly makes sense for the ``basic_parse -> parse``,\n``parse -> items`` and ``parse -> kvitems`` interactions.\n\nNote also that event interception\nis currently not supported\nby the ``async`` functions.\n\n\nPush interfaces\n---------------\n\nAll examples above use a file-like object as the data input\n(both the normal case, and for ``asyncio`` support),\nand hence are \"pull\" interfaces,\nwith the library reading data as necessary.\nIf for whatever reason it's not possible to use such method,\nyou can still **push** data\nthrough yet a different interface: `coroutines <https://www.python.org/dev/peps/pep-0342/>`_\n(via generators, not ``asyncio`` coroutines).\nCoroutines effectively allow users\nto send data to them at any point in time,\nwith a final *target* coroutine-like object\nreceiving the results.\n\nIn the following example\nthe user is doing the reading\ninstead of letting the library do it:\n\n.. code-block:: python\n\n   import ijson\n\n   @ijson.coroutine\n   def print_cities():\n      while True:\n         obj = (yield)\n         if obj['type'] != 'city':\n            continue\n         print(obj)\n\n   coro = ijson.items_coro(print_cities(), 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n   coro.close()\n\nAll four ijson iterators\nhave a ``*_coro`` counterpart\nthat work by pushing data into them.\nInstead of receiving a file-like object\nand option buffer size as arguments,\nthey receive a single ``target`` argument,\nwhich should be a coroutine-like object\n(anything implementing a ``send`` method)\nthrough which results will be published.\n\nAn alternative to providing a coroutine\nis to use ``ijson.sendable_list`` to accumulate results,\nproviding the list is cleared after each parsing iteration,\nlike this:\n\n.. code-block:: python\n\n   import ijson\n\n   events = ijson.sendable_list()\n   coro = ijson.items_coro(events, 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n      process_accumulated_events(events)\n      del events[:]\n   coro.close()\n   process_accumulated_events(events)\n\n\n.. _options:\n\nOptions\n=======\n\nAdditional options are supported by **all** ijson functions\nto give users more fine-grained control over certain operations:\n\n- The ``use_float`` option (defaults to ``False``)\n  controls how non-integer values are returned to the user.\n  If set to ``True`` users receive ``float()`` values;\n  otherwise ``Decimal`` values are constructed.\n  Note that building ``float`` values is usually faster,\n  but on the other hand there might be loss of precision\n  (which most applications will not care about)\n  and will raise an exception when overflow occurs\n  (e.g., if ``1e400`` is encountered).\n  This option also has the side-effect\n  that integer numbers bigger than ``2^64``\n  (but *sometimes* ``2^32``, see capabilities_)\n  will also raise an overflow error,\n  due to similar reasons.\n  Future versions of ijson\n  might change the default value of this option\n  to ``True``.\n- The ``multiple_values`` option (defaults to ``False``)\n  controls whether multiple top-level values are supported.\n  JSON content should contain a single top-level value\n  (see `the JSON Grammar <https://tools.ietf.org/html/rfc7159#section-2>`_).\n  However there are plenty of JSON files out in the wild\n  that contain multiple top-level values,\n  often separated by newlines.\n  By default ijson will fail to process these\n  with a ``parse error: trailing garbage`` error\n  unless ``multiple_values=True`` is specified.\n- Similarly the ``allow_comments`` option (defaults to ``False``)\n  controls whether C-style comments (e.g., ``/* a comment */``),\n  which are not supported by the JSON standard,\n  are allowed in the content or not.\n- For functions taking a file-like object,\n  an additional ``buf_size`` option (defaults to ``65536`` or 64KB)\n  specifies the amount of bytes the library\n  should attempt to read each time.\n- The ``items`` and ``kvitems`` functions, and all their variants,\n  have an optional ``map_type`` argument (defaults to ``dict``)\n  used to construct objects from the JSON stream.\n  This should be a dict-like type supporting item assignment.\n\n\nEvents\n======\n\nWhen using the lower-level ``ijson.parse`` function,\nthree-element tuples are generated\ncontaining a prefix, an event name, and a value.\nEvents will be one of the following:\n\n- ``start_map`` and ``end_map`` indicate\n  the beginning and end of a JSON object, respectively.\n  They carry a ``None`` as their value.\n- ``start_array`` and ``end_array`` indicate\n  the beginning and end of a JSON array, respectively.\n  They also carry a ``None`` as their value.\n- ``map_key`` indicates the name of a field in a JSON object.\n  Its associated value is the name itself.\n- ``null``, ``boolean``, ``integer``, ``double``, ``number`` and ``string``\n  all indicate actual content, which is stored in the associated value.\n\n\n.. _prefix:\n\nPrefix\n======\n\nA prefix represents the context within a JSON document\nwhere an event originates at.\nIt works as follows:\n\n- It starts as an empty string.\n- A ``<name>`` part is appended when the parser starts parsing the contents\n  of a JSON object member called ``name``,\n  and removed once the content finishes.\n- A literal ``item`` part is appended when the parser is parsing\n  elements of a JSON array,\n  and removed when the array ends.\n- Parts are separated by ``.``.\n\nWhen using the ``ijson.items`` function,\nthe prefix works as the selection\nfor which objects should be automatically built and returned by ijson.\n\n\n.. _backends:\n\nBackends\n========\n\nIjson provides several implementations of the actual parsing in the form of\nbackends located in ijson/backends:\n\n- ``yajl2_c``: a C extension using `YAJL <http://lloyd.github.io/yajl/>`__ 2.x.\n  This is the fastest, but *might* require a compiler and the YAJL development files\n  to be present when installing this package.\n  Binary wheel distributions exist for major platforms/architectures to spare users\n  from having to compile the package.\n- ``yajl2_cffi``: wrapper around `YAJL <http://lloyd.github.io/yajl/>`__ 2.x\n  using CFFI.\n- ``yajl2``: wrapper around YAJL 2.x using ctypes, for when you can't use CFFI\n  for some reason.\n- ``yajl``: deprecated YAJL 1.x + ctypes wrapper, for even older systems.\n- ``python``: pure Python parser, good to use with PyPy\n\nThis list of backend names is available under the ``ijson.ALL_BACKENDS`` constant.\n\nYou can import a specific backend and use it in the same way as the top level\nlibrary:\n\n.. code-block::  python\n\n    import ijson.backends.yajl2_cffi as ijson\n\n    for item in ijson.items(...):\n        # ...\n\nImporting the top level library as ``import ijson``\nuses the first available backend in the same order of the list above,\nand its name is recorded under ``ijson.backend``.\nIf the ``IJSON_BACKEND`` environment variable is set\nits value takes precedence and is used to select the default backend.\n\nYou can also use the ``ijson.get_backend`` function\nto get a specific backend based on a name:\n\n.. code-block:: python\n\n    backend = ijson.get_backend('yajl2_c')\n    for item in backend.items(...):\n        # ...\n\n\n.. _capabilities:\n\nCapabilities\n------------\n\nApart from their performance,\nall backends are designed to support the same capabilities.\nThere are however some small known differences,\nall of which can be queried by inspecting\nthe ``capabilities`` module constant.\nIt contains the following members:\n\n* ``c_comments``: C-style comments are supported.\n* ``multiple_values``: multiple top-level JSON values are supported.\n* ``detects_invalid_leading_zeros``: numbers with leading zeroes\n  are reported as invalid (as they should, as pert the JSON standard),\n  raising a ``ValueError``.\n* ``detects_incomplete_json_tokens``: detects incomplete JSON tokens\n  at the end of an incomplete document (e.g., ``{\"a\": fals``),\n  raising an ``IncompleteJSONError``.\n* ``int64``: when using ``use_float=True``,\n    values greater than or equal to ``2^32`` are correctly returned.\n\nThese capabilities are supported by all backends,\nwith the following exceptions:\n\n* The ``yajl`` backend doesn't support ``multiple_values``,\n  ``detects_invalid_leading_zeros`` and ``detects_incomplete_json_tokens``.\n  It also doesn't support ``int64``\n  in platforms with a 32-bit C ``long`` type.\n\n* The ``python`` backend doesn't support ``c_comments``.\n\n\nPerformance tips\n================\n\nIn more-or-less decreasing order,\nthese are the most common actions you can take\nto ensure you get most of the performance\nout of ijson:\n\n- Make sure you use the fastest backend available.\n  See backends_ for details.\n- If you know your JSON data\n  contains only numbers that are \"well behaved\"\n  consider turning on the ``use_float`` option.\n  See options_ for details.\n- Make sure you feed ijson with binary data\n  instead of text data.\n  See faq_ #1 for details.\n- Play with the ``buf_size`` option,\n  as depending on your data source and your system\n  a value different from the default\n  might show better performance.\n  See options_ for details.\n\nThe benchmarking_ tool should help\nwith trying some of these options\nand observing their effect on your input files.\n\n\n.. _faq:\n\nFAQ\n===\n\n#. **Q**: Does ijson work with ``bytes`` or ``str`` values?\n\n   **A**: In short: both are accepted as input, outputs are only ``str``.\n\n   All ijson functions expecting a file-like object\n   should ideally be given one\n   that is opened in binary mode\n   (i.e., its ``read`` function returns ``bytes`` objects, not ``str``).\n   However if a text-mode file object is given\n   then the library will automatically\n   encode the strings into UTF-8 bytes.\n   A warning is currently issued (but not visible by default)\n   alerting users about this automatic conversion.\n\n   On the other hand ijson always returns text data\n   (JSON string values, object member names, event names, etc)\n   as ``str`` objects.\n   This mimics the behavior of the system ``json`` module.\n\n#. **Q**: How are numbers dealt with?\n\n   **A**: ijson returns ``int`` values for integers\n   and ``decimal.Decimal`` values for floating-point numbers.\n   This is mostly because of historical reasons.\n   Since 3.1 a new ``use_float`` option (defaults to ``False``)\n   is available to return ``float`` values instead.\n   See the options_ section for details.\n\n#. **Q**: I'm getting an ``UnicodeDecodeError``, or an ``IncompleteJSONError`` with no message\n\n   **A**: This error is caused by byte sequences that are not valid in UTF-8.\n   In other words, the data given to ijson is not *really* UTF-8 encoded,\n   or at least not properly.\n\n   Depending on where the data comes from you have different options:\n\n   * If you have control over the source of the data, fix it.\n\n   * If you have a way to intercept the data flow,\n     do so and pass it through a \"byte corrector\".\n     For instance, if you have a shell pipeline\n     feeding data through ``stdin`` into your process\n     you can add something like ``... | iconv -f utf8 -t utf8 -c | ...``\n     in between to correct invalid byte sequences.\n\n   * If you are working purely in python,\n     you can create a UTF-8 decoder\n     using codecs' `incrementaldecoder <https://docs.python.org/3/library/codecs.html#codecs.getincrementaldecoder>`_\n     to leniently decode your bytes into strings,\n     and feed those strings (using a file-like class) into ijson\n     (see our `string_reader_async internal class <https://github.com/ICRAR/ijson/blob/0157f3c65a7986970030d3faa75979ee205d3806/ijson/utils35.py#L19>`_\n     for some inspiration).\n\n   In the future ijson might offer something out of the box\n   to deal with invalid UTF-8 byte sequences.\n\n#. **Q**: I'm getting ``parse error: trailing garbage`` or ``Additional data found`` errors\n\n   **A**: This error signals that the input\n   contains more data than the top-level JSON value it's meant to contain.\n   This is *usually* caused by JSON data sources\n   containing multiple values, and is *usually* solved\n   by passing the ``multiple_values=True`` to the ijson function in use.\n   See the options_ section for details.\n\n\nAcknowledgements\n================\n\nijson was originally developed and actively maintained until 2016\nby `Ivan Sagalaev <http://softwaremaniacs.org/>`_.\nIn 2019 he\n`handed over <https://github.com/isagalaev/ijson/pull/58#issuecomment-500596815>`_\nthe maintenance of the project and the PyPI ownership.\n\nPython parser in ijson is relatively simple thanks to `Douglas Crockford\n<http://www.crockford.com/>`_ who invented a strict, easy to parse syntax.\n\nThe `YAJL <https://lloyd.github.io/yajl>`__ library by `Lloyd Hilaiel\n<http://lloyd.io/>`_ is the most popular and efficient way to parse JSON in an\niterative fashion.\nWhen building the library ourselves,\nwe use `our own fork <https://github.com/rtobar/yajl>`__\nthat contains fixes for all known CVEs.\n\nIjson was inspired by `yajl-py <http://pykler.github.com/yajl-py/>`_ wrapper by\n`Hatem Nassrat <http://www.nassrat.ca/>`_. Though ijson borrows almost nothing\nfrom the actual yajl-py code it was used as an example of integration with yajl\nusing ctypes.\n",
      "keywords": "",
      "platform": [],
      "classifiers": [
        "Development Status :: 5 - Production/Stable",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Programming Language :: Python :: 3.13",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Environment :: MetaData :: IBM Python Ecosystem"
      ],
      "download_url": "",
      "supported_platform": [],
      "comment": "",
      "provides": [],
      "requires": [],
      "obsoletes": [],
      "project_urls": [
        "Homepage, https://github.com/ICRAR/ijson"
      ],
      "provides_dist": [],
      "obsoletes_dist": [],
      "requires_dist": [],
      "requires_external": [],
      "requires_python": ">=3.9",
      "description_content_type": "text/x-rst",
      "provides_extras": [],
      "dynamic": [
        "license-file"
      ],
      "license_expression": "BSD-3-Clause AND ISC",
      "license_file": [
        "LICENSE.txt"
      ],
      "+links": [
        {
          "rel": "releasefile",
          "hash_spec": "sha256=78b8884b6890829b19e71ac795a80bbdc2a0e8c9be1ea98743faef283e1b620c",
          "hashes": {
            "sha256": "78b8884b6890829b19e71ac795a80bbdc2a0e8c9be1ea98743faef283e1b620c"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/78b/8884b6890829b/ijson-3.4.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                35
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=d38deb26c87668ba6ee70224ca45f5e7af9a155d78287e3b28228209b6113d00",
          "hashes": {
            "sha256": "d38deb26c87668ba6ee70224ca45f5e7af9a155d78287e3b28228209b6113d00"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/d38/deb26c87668ba/ijson-3.4.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                35
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=b727c9f2f0f00099d8131309412741843f04aa68e8bb14b6c53ce83d4bfef969",
          "hashes": {
            "sha256": "b727c9f2f0f00099d8131309412741843f04aa68e8bb14b6c53ce83d4bfef969"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/b72/7c9f2f0f00099/ijson-3.4.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                36
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=8330dc254b75da805c314085f2f2a92cf745c82885e922e3c1f0a9c0d82a1050",
          "hashes": {
            "sha256": "8330dc254b75da805c314085f2f2a92cf745c82885e922e3c1f0a9c0d82a1050"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/833/0dc254b75da80/ijson-3.4.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                37
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=f748025b845137d9a872cde434ea32e914fa69a02196f70e98d003f3c1a1ae4c",
          "hashes": {
            "sha256": "f748025b845137d9a872cde434ea32e914fa69a02196f70e98d003f3c1a1ae4c"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/f74/8025b845137d9/ijson-3.4.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                37
              ],
              "dst": "ppc64le/linux"
            }
          ]
        }
      ]
    },
    "3.5.0": {
      "name": "ijson",
      "version": "3.5.0",
      "metadata_version": "2.4",
      "summary": "Iterative JSON parser with standard Python iterator interfaces",
      "home_page": "",
      "author": "",
      "author_email": "Rodrigo Tobar <rtobar@icrar.org>, Ivan Sagalaev <maniac@softwaremaniacs.org>",
      "maintainer": "",
      "maintainer_email": "",
      "license": "",
      "description": ".. image:: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://github.com/ICRAR/ijson/actions/workflows/fast-built-and-test.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://coveralls.io/repos/github/ICRAR/ijson/badge.svg?branch=master\n    :target: https://coveralls.io/github/ICRAR/ijson?branch=master\n\n.. image:: https://badge.fury.io/py/ijson.svg\n    :target: https://badge.fury.io/py/ijson\n\n.. image:: https://img.shields.io/pypi/pyversions/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dd/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dw/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dm/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n\n=====\nijson\n=====\n\nIjson is an iterative JSON parser with standard Python iterator interfaces.\n\n.. contents::\n   :local:\n\n\nInstallation\n============\n\nIjson is hosted in PyPI, so you should be able to install it via ``pip``::\n\n  pip install ijson\n\nBinary wheels are provided\nfor major platforms\nand python versions.\nThese are built and published automatically\nusing `cibuildwheel <https://cibuildwheel.readthedocs.io/en/stable/>`_\nvia GitHub Actions.\n\n\nUsage\n=====\n\nAll usage example will be using a JSON document describing geographical\nobjects:\n\n.. code-block:: json\n\n    {\n      \"earth\": {\n        \"europe\": [\n          {\"name\": \"Paris\", \"type\": \"city\", \"info\": { ... }},\n          {\"name\": \"Thames\", \"type\": \"river\", \"info\": { ... }},\n          // ...\n        ],\n        \"america\": [\n          {\"name\": \"Texas\", \"type\": \"state\", \"info\": { ... }},\n          // ...\n        ]\n      }\n    }\n\n\nHigh-level interfaces\n---------------------\n\nijson works by continuously reading data from a JSON stream provided by the user.\nThis is presented as a file-like object.\nIn particular it must provide a ``read(size)`` method\nreturning either ``bytes`` (preferably) or ``str``.\nExample file-like objects are\nfiles opened with ``open``,\nHTTP/HTTPS requests made using ``urllib.request.urlopen``,\n``socket.socket`` objects,\nand more.\n\nThe most common usage of ijson is to yield native Python objects\nlocated under a prefix.\nThis is done using the ``items`` function.\nHere's how to process all European cities:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    objects = ijson.items(f, 'earth.europe.item')\n    cities = (o for o in objects if o['type'] == 'city')\n    for city in cities:\n        do_something_with(city)\n\nFor how to build a prefix see the prefix_ section below.\n\nOther times it might be useful to iterate over object members\nrather than objects themselves (e.g., when objects are too big).\nIn that case one can use the ``kvitems`` function instead:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    european_places = ijson.kvitems(f, 'earth.europe.item')\n    names = (v for k, v in european_places if k == 'name')\n    for name in names:\n        do_something_with(name)\n\n\nLower-level interfaces\n----------------------\n\nSometimes when dealing with a particularly large JSON payload it may worth to\nnot even construct individual Python objects and react on individual events\nimmediately producing some result.\nThis is achieved using the ``parse`` function:\n\n.. code-block::  python\n\n    import ijson\n\n    parser = ijson.parse(urlopen('http://.../'))\n    stream.write('<geo>')\n    for prefix, event, value in parser:\n        if (prefix, event) == ('earth', 'map_key'):\n            stream.write('<%s>' % value)\n            continent = value\n        elif prefix.endswith('.name'):\n            stream.write('<object name=\"%s\"/>' % value)\n        elif (prefix, event) == ('earth.%s' % continent, 'end_map'):\n            stream.write('</%s>' % continent)\n    stream.write('</geo>')\n\nEven more bare-bones is the ability to react on individual events\nwithout even calculating a prefix\nusing the ``basic_parse`` function:\n\n.. code-block:: python\n\n    import ijson\n\n    events = ijson.basic_parse(urlopen('http://.../'))\n    num_names = sum(1 for event, value in events\n                    if event == 'map_key' and value == 'name')\n\n\nCommand line\n------------\n\nA command line utility is included with ijson\nto help visualise the output of each of the routines above.\nIt reads JSON from the standard input,\nand it prints the results of the parsing method chosen by the user\nto the standard output.\n\nThe tool is available by running the ``ijson.dump`` module.\nFor example::\n\n $> echo '{\"A\": 0, \"B\": [1, 2, 3, 4]}' | python -m ijson.dump -m parse\n #: path, name, value\n --------------------\n 0: , start_map, None\n 1: , map_key, A\n 2: A, number, 0\n 3: , map_key, B\n 4: B, start_array, None\n 5: B.item, number, 1\n 6: B.item, number, 2\n 7: B.item, number, 3\n 8: B.item, number, 4\n 9: B, end_array, None\n 10: , end_map, None\n\nUsing ``-h/--help`` will show all available options.\n\n\nBenchmarking\n------------\n\nA command line utility is included with ijson\nto help benchmarking the different methods offered by the package.\nIt offers some built-in example inputs\nthat try to mimic different scenarios,\nbut more importantly it also supports user-provided inputs.\nYou can also specify which backends to time,\nnumber of iterations,\nand more.\n\nThe tool is available by running the ``ijson.benchmark`` module.\nFor example::\n\n $> python -m ijson.benchmark my/json/file.json -m items -p values.item\n\nUsing ``-h/--help`` will show all available options.\n\n\n``bytes``/``str`` support\n-------------------------\n\nAlthough not usually how they are meant to be run,\nall the functions above also accept\n``bytes`` and ``str`` objects\ndirectly as inputs.\nThese are then internally wrapped into a file object,\nand further processed.\nThis is useful for testing and prototyping,\nbut probably not extremely useful in real-life scenarios.\n\n\nIterator support\n----------------\n\nIn many situations the direct input users want to pass to ijson\nis an iterator (e.g., a generator) rather than a file-like object.\nijson provides a built-in adapter to bridge this gap:\n\n- ``ijson.from_iter(iterable_or_async_iterable_of_bytes)``\n\n\n``asyncio`` support\n-------------------\n\nAll of the methods above\nwork also on file-like asynchronous objects,\nso they can be iterated asynchronously.\nIn other words, something like this:\n\n.. code-block:: python\n\n   import asyncio\n   import ijson\n\n   async def run():\n      f = await async_urlopen('http://..../')\n      async for object in ijson.items(f, 'earth.europe.item'):\n         if object['type'] == 'city':\n            do_something_with(city)\n   asyncio.run(run())\n\nAn explicit set of ``*_async`` functions also exists\noffering the same functionality,\nexcept they will fail if anything other\nthan a file-like asynchronous object is given to them.\n(so the example above can also be written using ``ijson.items_async``).\nIn fact in ijson version 3.0\nthis was the only way to access\nthe ``asyncio`` support.\n\n\nIntercepting events\n-------------------\n\nThe four routines shown above\ninternally chain against each other:\ntuples generated by ``basic_parse``\nare the input for ``parse``,\nwhose results are the input to ``kvitems`` and ``items``.\n\nNormally users don't see this interaction,\nas they only care about the final output\nof the function they invoked,\nbut there are occasions when tapping\ninto this invocation chain this could be handy.\nThis is supported\nby passing the output of one function\n(i.e., an iterable of events, usually a generator)\nas the input of another,\nopening the door for user event filtering or injection.\n\nFor instance if one wants to skip some content\nbefore full item parsing:\n\n.. code-block:: python\n\n  import io\n  import ijson\n\n  parse_events = ijson.parse(io.BytesIO(b'[\"skip\", {\"a\": 1}, {\"b\": 2}, {\"c\": 3}]'))\n  while True:\n      prefix, event, value = next(parse_events)\n      if value == \"skip\":\n          break\n  for obj in ijson.items(parse_events, 'item'):\n      print(obj)\n\n\nNote that this interception\nonly makes sense for the ``basic_parse -> parse``,\n``parse -> items`` and ``parse -> kvitems`` interactions.\n\nNote also that event interception\nis currently not supported\nby the ``async`` functions.\n\n\nPush interfaces\n---------------\n\nAll examples above use a file-like object as the data input\n(both the normal case, and for ``asyncio`` support),\nand hence are \"pull\" interfaces,\nwith the library reading data as necessary.\nIf for whatever reason it's not possible to use such method,\nyou can still **push** data\nthrough yet a different interface: `coroutines <https://www.python.org/dev/peps/pep-0342/>`_\n(via generators, not ``asyncio`` coroutines).\nCoroutines effectively allow users\nto send data to them at any point in time,\nwith a final *target* coroutine-like object\nreceiving the results.\n\nIn the following example\nthe user is doing the reading\ninstead of letting the library do it:\n\n.. code-block:: python\n\n   import ijson\n\n   @ijson.coroutine\n   def print_cities():\n      while True:\n         obj = (yield)\n         if obj['type'] != 'city':\n            continue\n         print(obj)\n\n   coro = ijson.items_coro(print_cities(), 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n   coro.close()\n\nAll four ijson iterators\nhave a ``*_coro`` counterpart\nthat work by pushing data into them.\nInstead of receiving a file-like object\nand option buffer size as arguments,\nthey receive a single ``target`` argument,\nwhich should be a coroutine-like object\n(anything implementing a ``send`` method)\nthrough which results will be published.\n\nAn alternative to providing a coroutine\nis to use ``ijson.sendable_list`` to accumulate results,\nproviding the list is cleared after each parsing iteration,\nlike this:\n\n.. code-block:: python\n\n   import ijson\n\n   events = ijson.sendable_list()\n   coro = ijson.items_coro(events, 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n      process_accumulated_events(events)\n      del events[:]\n   coro.close()\n   process_accumulated_events(events)\n\n\nOptions\n=======\n\nAdditional options are supported by **all** ijson functions\nto give users more fine-grained control over certain operations:\n\n- The ``use_float`` option (defaults to ``False``)\n  controls how non-integer values are returned to the user.\n  If set to ``True`` users receive ``float()`` values;\n  otherwise ``Decimal`` values are constructed.\n  Note that building ``float`` values is usually faster,\n  but on the other hand there might be loss of precision\n  (which most applications will not care about)\n  and will raise an exception when overflow occurs\n  (e.g., if ``1e400`` is encountered).\n  This option also has the side-effect\n  that integer numbers bigger than ``2^64``\n  (but *sometimes* ``2^32``, see capabilities_)\n  will also raise an overflow error,\n  due to similar reasons.\n  Future versions of ijson\n  might change the default value of this option\n  to ``True``.\n- The ``multiple_values`` option (defaults to ``False``)\n  controls whether multiple top-level values are supported.\n  JSON content should contain a single top-level value\n  (see `the JSON Grammar <https://tools.ietf.org/html/rfc7159#section-2>`_).\n  However there are plenty of JSON files out in the wild\n  that contain multiple top-level values,\n  often separated by newlines.\n  By default ijson will fail to process these\n  with a ``parse error: trailing garbage`` error\n  unless ``multiple_values=True`` is specified.\n- Similarly the ``allow_comments`` option (defaults to ``False``)\n  controls whether C-style comments (e.g., ``/* a comment */``),\n  which are not supported by the JSON standard,\n  are allowed in the content or not.\n- For functions taking a file-like object,\n  an additional ``buf_size`` option (defaults to ``65536`` or 64KB)\n  specifies the amount of bytes the library\n  should attempt to read each time.\n- The ``items`` and ``kvitems`` functions, and all their variants,\n  have an optional ``map_type`` argument (defaults to ``dict``)\n  used to construct objects from the JSON stream.\n  This should be a dict-like type supporting item assignment.\n\n\nEvents\n======\n\nWhen using the lower-level ``ijson.parse`` function,\nthree-element tuples are generated\ncontaining a prefix, an event name, and a value.\nEvents will be one of the following:\n\n- ``start_map`` and ``end_map`` indicate\n  the beginning and end of a JSON object, respectively.\n  They carry a ``None`` as their value.\n- ``start_array`` and ``end_array`` indicate\n  the beginning and end of a JSON array, respectively.\n  They also carry a ``None`` as their value.\n- ``map_key`` indicates the name of a field in a JSON object.\n  Its associated value is the name itself.\n- ``null``, ``boolean``, ``integer``, ``double``, ``number`` and ``string``\n  all indicate actual content, which is stored in the associated value.\n\n\nPrefix\n======\n\nA prefix represents the context within a JSON document\nwhere an event originates at.\nIt works as follows:\n\n- It starts as an empty string.\n- A ``<name>`` part is appended when the parser starts parsing the contents\n  of a JSON object member called ``name``,\n  and removed once the content finishes.\n- A literal ``item`` part is appended when the parser is parsing\n  elements of a JSON array,\n  and removed when the array ends.\n- Parts are separated by ``.``.\n\nWhen using the ``ijson.items`` function,\nthe prefix works as the selection\nfor which objects should be automatically built and returned by ijson.\n\n\nBackends\n========\n\nIjson provides several implementations of the actual parsing in the form of\nbackends located in ijson/backends:\n\n- ``yajl2_c``: a C extension using `YAJL <http://lloyd.github.io/yajl/>`__ 2.x.\n  This is the fastest, but *might* require a compiler and the YAJL development files\n  to be present when installing this package.\n  Binary wheel distributions exist for major platforms/architectures to spare users\n  from having to compile the package.\n- ``yajl2_cffi``: wrapper around `YAJL <http://lloyd.github.io/yajl/>`__ 2.x\n  using CFFI.\n- ``yajl2``: wrapper around YAJL 2.x using ctypes, for when you can't use CFFI\n  for some reason.\n- ``yajl``: deprecated YAJL 1.x + ctypes wrapper, for even older systems.\n- ``python``: pure Python parser, good to use with PyPy\n\nThis list of backend names is available under the ``ijson.ALL_BACKENDS`` constant.\n\nYou can import a specific backend and use it in the same way as the top level\nlibrary:\n\n.. code-block::  python\n\n    import ijson.backends.yajl2_cffi as ijson\n\n    for item in ijson.items(...):\n        # ...\n\nImporting the top level library as ``import ijson``\nuses the first available backend in the same order of the list above,\nand its name is recorded under ``ijson.backend``.\nIf the ``IJSON_BACKEND`` environment variable is set\nits value takes precedence and is used to select the default backend.\n\nYou can also use the ``ijson.get_backend`` function\nto get a specific backend based on a name:\n\n.. code-block:: python\n\n    backend = ijson.get_backend('yajl2_c')\n    for item in backend.items(...):\n        # ...\n\n\nCapabilities\n------------\n\nApart from their performance,\nall backends are designed to support the same capabilities.\nThere are however some small known differences,\nall of which can be queried by inspecting\nthe ``capabilities`` module constant.\nIt contains the following members:\n\n* ``c_comments``: C-style comments are supported.\n* ``multiple_values``: multiple top-level JSON values are supported.\n* ``detects_invalid_leading_zeros``: numbers with leading zeroes\n  are reported as invalid (as they should, as pert the JSON standard),\n  raising a ``ValueError``.\n* ``detects_incomplete_json_tokens``: detects incomplete JSON tokens\n  at the end of an incomplete document (e.g., ``{\"a\": fals``),\n  raising an ``IncompleteJSONError``.\n* ``int64``: when using ``use_float=True``,\n    values greater than or equal to ``2^32`` are correctly returned.\n\nThese capabilities are supported by all backends,\nwith the following exceptions:\n\n* The ``yajl`` backend doesn't support ``multiple_values``,\n  ``detects_invalid_leading_zeros`` and ``detects_incomplete_json_tokens``.\n  It also doesn't support ``int64``\n  in platforms with a 32-bit C ``long`` type.\n\n* The ``python`` backend doesn't support ``c_comments``.\n\n\nPerformance tips\n================\n\nIn more-or-less decreasing order,\nthese are the most common actions you can take\nto ensure you get most of the performance\nout of ijson:\n\n- Make sure you use the fastest backend available.\n  See backends_ for details.\n- If you know your JSON data\n  contains only numbers that are \"well behaved\"\n  consider turning on the ``use_float`` option.\n  See options_ for details.\n- Make sure you feed ijson with binary data\n  instead of text data.\n  See faq_ #1 for details.\n- Play with the ``buf_size`` option,\n  as depending on your data source and your system\n  a value different from the default\n  might show better performance.\n  See options_ for details.\n\nThe benchmarking_ tool should help\nwith trying some of these options\nand observing their effect on your input files.\n\n\nFAQ\n===\n\n#. **Q**: Does ijson work with ``bytes`` or ``str`` values?\n\n   **A**: In short: both are accepted as input, outputs are only ``str``.\n\n   All ijson functions expecting a file-like object\n   should ideally be given one\n   that is opened in binary mode\n   (i.e., its ``read`` function returns ``bytes`` objects, not ``str``).\n   However if a text-mode file object is given\n   then the library will automatically\n   encode the strings into UTF-8 bytes.\n   A warning is currently issued (but not visible by default)\n   alerting users about this automatic conversion.\n\n   On the other hand ijson always returns text data\n   (JSON string values, object member names, event names, etc)\n   as ``str`` objects.\n   This mimics the behavior of the system ``json`` module.\n\n#. **Q**: How are numbers dealt with?\n\n   **A**: ijson returns ``int`` values for integers\n   and ``decimal.Decimal`` values for floating-point numbers.\n   This is mostly because of historical reasons.\n   Since 3.1 a new ``use_float`` option (defaults to ``False``)\n   is available to return ``float`` values instead.\n   See the options_ section for details.\n\n#. **Q**: I'm getting an ``UnicodeDecodeError``, or an ``IncompleteJSONError`` with no message\n\n   **A**: This error is caused by byte sequences that are not valid in UTF-8.\n   In other words, the data given to ijson is not *really* UTF-8 encoded,\n   or at least not properly.\n\n   Depending on where the data comes from you have different options:\n\n   * If you have control over the source of the data, fix it.\n\n   * If you have a way to intercept the data flow,\n     do so and pass it through a \"byte corrector\".\n     For instance, if you have a shell pipeline\n     feeding data through ``stdin`` into your process\n     you can add something like ``... | iconv -f utf8 -t utf8 -c | ...``\n     in between to correct invalid byte sequences.\n\n   * If you are working purely in python,\n     you can create a UTF-8 decoder\n     using codecs' `incrementaldecoder <https://docs.python.org/3/library/codecs.html#codecs.getincrementaldecoder>`_\n     to leniently decode your bytes into strings,\n     and feed those strings (using a file-like class) into ijson\n     (see our `string_reader_async internal class <https://github.com/ICRAR/ijson/blob/0157f3c65a7986970030d3faa75979ee205d3806/ijson/utils35.py#L19>`_\n     for some inspiration).\n\n   In the future ijson might offer something out of the box\n   to deal with invalid UTF-8 byte sequences.\n\n#. **Q**: I'm getting ``parse error: trailing garbage`` or ``Additional data found`` errors\n\n   **A**: This error signals that the input\n   contains more data than the top-level JSON value it's meant to contain.\n   This is *usually* caused by JSON data sources\n   containing multiple values, and is *usually* solved\n   by passing the ``multiple_values=True`` to the ijson function in use.\n   See the options_ section for details.\n\n#. **Q**: How do I use ijson with ``requests`` or ``httpx``\n\n   **A**: The ``requests`` library downloads the body of the HTTP response immediately by default.\n   To stream JSON into ijson, pass ``stream=True`` and adapt the byte iterator:\n\n   .. code-block:: python\n\n      import requests\n      import ijson\n\n      with requests.get('https://..', stream=True) as resp:\n          resp.raise_for_status()\n          f = ijson.from_iter(resp.iter_content(chunk_size=64*1024))\n          objects = ijson.items(f, 'earth.europe.item')\n          cities = (o for o in objects if o['type'] == 'city')\n          for city in cities:\n            do_something_with(city)\n\n   You can also pass ``Response.raw`` directly (it's a file-like object),\n   but using ``iter_content`` is preferred because ``requests`` will transparently\n   handle HTTP transfer encodings (e.g., gzip, chunked).\n\n\n   For async usage with ``httpx``:\n\n   .. code-block:: python\n\n      import httpx\n      import ijson\n\n      async with httpx.AsyncClient() as client:\n          async with client.stream('GET', 'https://..') as resp:\n              resp.raise_for_status()\n              f = ijson.from_iter(resp.aiter_bytes())\n              objects = ijson.items(f, 'earth.europe.item')\n              cities = (o async for o in objects if o['type'] == 'city')\n              async for city in cities:\n                do_something_with(city)\n\n\nAcknowledgements\n================\n\nijson was originally developed and actively maintained until 2016\nby `Ivan Sagalaev <http://softwaremaniacs.org/>`_.\nIn 2019 he\n`handed over <https://github.com/isagalaev/ijson/pull/58#issuecomment-500596815>`_\nthe maintenance of the project and the PyPI ownership.\n\nPython parser in ijson is relatively simple thanks to `Douglas Crockford\n<http://www.crockford.com/>`_ who invented a strict, easy to parse syntax.\n\nThe `YAJL <https://lloyd.github.io/yajl>`__ library by `Lloyd Hilaiel\n<http://lloyd.io/>`_ is the most popular and efficient way to parse JSON in an\niterative fashion.\nWhen building the library ourselves,\nwe use `our own fork <https://github.com/rtobar/yajl>`__\nthat contains fixes for all known CVEs.\n\nIjson was inspired by `yajl-py <http://pykler.github.com/yajl-py/>`_ wrapper by\n`Hatem Nassrat <http://www.nassrat.ca/>`_. Though ijson borrows almost nothing\nfrom the actual yajl-py code it was used as an example of integration with yajl\nusing ctypes.\n",
      "keywords": "",
      "platform": [],
      "classifiers": [
        "Development Status :: 5 - Production/Stable",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Programming Language :: Python :: 3.13",
        "Programming Language :: Python :: 3.14",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Environment :: MetaData :: IBM Python Ecosystem"
      ],
      "download_url": "",
      "supported_platform": [],
      "comment": "",
      "provides": [],
      "requires": [],
      "obsoletes": [],
      "project_urls": [
        "Homepage, https://github.com/ICRAR/ijson"
      ],
      "provides_dist": [],
      "obsoletes_dist": [],
      "requires_dist": [],
      "requires_external": [],
      "requires_python": ">=3.9",
      "description_content_type": "text/x-rst",
      "provides_extras": [],
      "dynamic": [
        "license-file"
      ],
      "license_expression": "BSD-3-Clause AND ISC",
      "license_file": [
        "LICENSE.txt"
      ],
      "+links": [
        {
          "rel": "releasefile",
          "hash_spec": "sha256=8c921730e41e53b7d356ed427094b666510e1ce60231bb2ef93f781c14c17fa4",
          "hashes": {
            "sha256": "8c921730e41e53b7d356ed427094b666510e1ce60231bb2ef93f781c14c17fa4"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/8c9/21730e41e53b7/ijson-3.5.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                40
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=3089f70d77063bfd6de5791525dab04bf72ff38a88baa74e5ffbf8e79b252e62",
          "hashes": {
            "sha256": "3089f70d77063bfd6de5791525dab04bf72ff38a88baa74e5ffbf8e79b252e62"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/308/9f70d77063bfd/ijson-3.5.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                40
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=105f8682ecaf6867027c3aee1598806ece67106e6689383ec2c4d7927e74ef04",
          "hashes": {
            "sha256": "105f8682ecaf6867027c3aee1598806ece67106e6689383ec2c4d7927e74ef04"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/105/f8682ecaf6867/ijson-3.5.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                41
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=1b8178d133aad651b7bacd513d59451a14d0ab3967a903ba4af980f84b8fe945",
          "hashes": {
            "sha256": "1b8178d133aad651b7bacd513d59451a14d0ab3967a903ba4af980f84b8fe945"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/1b8/178d133aad651/ijson-3.5.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                41
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=50cef37639fa4db44a476dfc135047ba8a432c885e221ba5b17c4c0d25304556",
          "hashes": {
            "sha256": "50cef37639fa4db44a476dfc135047ba8a432c885e221ba5b17c4c0d25304556"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/50c/ef37639fa4db4/ijson-3.5.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                42
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=e3bb80f184e63b12a3d8850a17ffbfd8f367bfc3bd9c91255995b389327de70c",
          "hashes": {
            "sha256": "e3bb80f184e63b12a3d8850a17ffbfd8f367bfc3bd9c91255995b389327de70c"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/e3b/b80f184e63b12/ijson-3.5.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                42
              ],
              "dst": "ppc64le/linux"
            }
          ]
        }
      ]
    },
    "3.3.0": {
      "name": "ijson",
      "version": "3.3.0",
      "metadata_version": "2.2",
      "summary": "Iterative JSON parser with standard Python iterator interfaces",
      "home_page": "https://github.com/ICRAR/ijson",
      "author": "Rodrigo Tobar, Ivan Sagalaev",
      "author_email": "rtobar@icrar.org, maniac@softwaremaniacs.org",
      "maintainer": "",
      "maintainer_email": "",
      "license": "BSD",
      "description": ".. image:: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://github.com/ICRAR/ijson/actions/workflows/fast-built-and-test.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://coveralls.io/repos/github/ICRAR/ijson/badge.svg?branch=master\n    :target: https://coveralls.io/github/ICRAR/ijson?branch=master\n\n.. image:: https://badge.fury.io/py/ijson.svg\n    :target: https://badge.fury.io/py/ijson\n\n.. image:: https://img.shields.io/pypi/pyversions/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dd/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dw/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dm/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n\n=====\nijson\n=====\n\nIjson is an iterative JSON parser with standard Python iterator interfaces.\n\n.. contents::\n   :local:\n\n\nInstallation\n============\n\nIjson is hosted in PyPI, so you should be able to install it via ``pip``::\n\n  pip install ijson\n\nBinary wheels are provided\nfor major platforms\nand python versions.\nThese are built and published automatically\nusing `cibuildwheel <https://cibuildwheel.readthedocs.io/en/stable/>`_\nvia GitHub Actions.\n\n\nUsage\n=====\n\nAll usage example will be using a JSON document describing geographical\nobjects:\n\n.. code-block:: json\n\n    {\n      \"earth\": {\n        \"europe\": [\n          {\"name\": \"Paris\", \"type\": \"city\", \"info\": { ... }},\n          {\"name\": \"Thames\", \"type\": \"river\", \"info\": { ... }},\n          // ...\n        ],\n        \"america\": [\n          {\"name\": \"Texas\", \"type\": \"state\", \"info\": { ... }},\n          // ...\n        ]\n      }\n    }\n\n\nHigh-level interfaces\n---------------------\n\nMost common usage is having ijson yield native Python objects out of a JSON\nstream located under a prefix.\nThis is done using the ``items`` function.\nHere's how to process all European cities:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    objects = ijson.items(f, 'earth.europe.item')\n    cities = (o for o in objects if o['type'] == 'city')\n    for city in cities:\n        do_something_with(city)\n\nFor how to build a prefix see the prefix_ section below.\n\nOther times it might be useful to iterate over object members\nrather than objects themselves (e.g., when objects are too big).\nIn that case one can use the ``kvitems`` function instead:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    european_places = ijson.kvitems(f, 'earth.europe.item')\n    names = (v for k, v in european_places if k == 'name')\n    for name in names:\n        do_something_with(name)\n\n\nLower-level interfaces\n----------------------\n\nSometimes when dealing with a particularly large JSON payload it may worth to\nnot even construct individual Python objects and react on individual events\nimmediately producing some result.\nThis is achieved using the ``parse`` function:\n\n.. code-block::  python\n\n    import ijson\n\n    parser = ijson.parse(urlopen('http://.../'))\n    stream.write('<geo>')\n    for prefix, event, value in parser:\n        if (prefix, event) == ('earth', 'map_key'):\n            stream.write('<%s>' % value)\n            continent = value\n        elif prefix.endswith('.name'):\n            stream.write('<object name=\"%s\"/>' % value)\n        elif (prefix, event) == ('earth.%s' % continent, 'end_map'):\n            stream.write('</%s>' % continent)\n    stream.write('</geo>')\n\nEven more bare-bones is the ability to react on individual events\nwithout even calculating a prefix\nusing the ``basic_parse`` function:\n\n.. code-block:: python\n\n    import ijson\n\n    events = ijson.basic_parse(urlopen('http://.../'))\n    num_names = sum(1 for event, value in events\n                    if event == 'map_key' and value == 'name')\n\n\n.. _command_line:\n\nCommand line\n------------\n\nA command line utility is included with ijson\nto help visualise the output of each of the routines above.\nIt reads JSON from the standard input,\nand it prints the results of the parsing method chosen by the user\nto the standard output.\n\nThe tool is available by running the ``ijson.dump`` module.\nFor example::\n\n $> echo '{\"A\": 0, \"B\": [1, 2, 3, 4]}' | python -m ijson.dump -m parse\n #: path, name, value\n --------------------\n 0: , start_map, None\n 1: , map_key, A\n 2: A, number, 0\n 3: , map_key, B\n 4: B, start_array, None\n 5: B.item, number, 1\n 6: B.item, number, 2\n 7: B.item, number, 3\n 8: B.item, number, 4\n 9: B, end_array, None\n 10: , end_map, None\n\nUsing ``-h/--help`` will show all available options.\n\n\n.. _benchmarking:\n\nBenchmarking\n------------\n\nA command line utility is included with ijson\nto help benchmarking the different methods offered by the package.\nIt offers some built-in example inputs\nthat try to mimic different scenarios,\nbut more importantly it also supports user-provided inputs.\nYou can also specify which backends to time,\nnumber of iterations,\nand more.\n\nThe tool is available by running the ``ijson.benchmark`` module.\nFor example::\n\n $> python -m ijson.benchmark my/json/file.json -m items -p values.item\n\nUsing ``-h/--help`` will show all available options.\n\n\n``bytes``/``str`` support\n-------------------------\n\nAlthough not usually how they are meant to be run,\nall the functions above also accept\n``bytes`` and ``str`` objects\ndirectly as inputs.\nThese are then internally wrapped into a file object,\nand further processed.\nThis is useful for testing and prototyping,\nbut probably not extremely useful in real-life scenarios.\n\n\n``asyncio`` support\n-------------------\n\nAll of the methods above\nwork also on file-like asynchronous objects,\nso they can be iterated asynchronously.\nIn other words, something like this:\n\n.. code-block:: python\n\n   import asyncio\n   import ijson\n\n   async def run():\n      f = await async_urlopen('http://..../')\n      async for object in ijson.items(f, 'earth.europe.item'):\n         if object['type'] == 'city':\n            do_something_with(city)\n   asyncio.run(run())\n\nAn explicit set of ``*_async`` functions also exists\noffering the same functionality,\nexcept they will fail if anything other\nthan a file-like asynchronous object is given to them.\n(so the example above can also be written using ``ijson.items_async``).\nIn fact in ijson version 3.0\nthis was the only way to access\nthe ``asyncio`` support.\n\n\nIntercepting events\n-------------------\n\nThe four routines shown above\ninternally chain against each other:\ntuples generated by ``basic_parse``\nare the input for ``parse``,\nwhose results are the input to ``kvitems`` and ``items``.\n\nNormally users don't see this interaction,\nas they only care about the final output\nof the function they invoked,\nbut there are occasions when tapping\ninto this invocation chain this could be handy.\nThis is supported\nby passing the output of one function\n(i.e., an iterable of events, usually a generator)\nas the input of another,\nopening the door for user event filtering or injection.\n\nFor instance if one wants to skip some content\nbefore full item parsing:\n\n.. code-block:: python\n\n  import io\n  import ijson\n\n  parse_events = ijson.parse(io.BytesIO(b'[\"skip\", {\"a\": 1}, {\"b\": 2}, {\"c\": 3}]'))\n  while True:\n      prefix, event, value = next(parse_events)\n      if value == \"skip\":\n          break\n  for obj in ijson.items(parse_events, 'item'):\n      print(obj)\n\n\nNote that this interception\nonly makes sense for the ``basic_parse -> parse``,\n``parse -> items`` and ``parse -> kvitems`` interactions.\n\nNote also that event interception\nis currently not supported\nby the ``async`` functions.\n\n\nPush interfaces\n---------------\n\nAll examples above use a file-like object as the data input\n(both the normal case, and for ``asyncio`` support),\nand hence are \"pull\" interfaces,\nwith the library reading data as necessary.\nIf for whatever reason it's not possible to use such method,\nyou can still **push** data\nthrough yet a different interface: `coroutines <https://www.python.org/dev/peps/pep-0342/>`_\n(via generators, not ``asyncio`` coroutines).\nCoroutines effectively allow users\nto send data to them at any point in time,\nwith a final *target* coroutine-like object\nreceiving the results.\n\nIn the following example\nthe user is doing the reading\ninstead of letting the library do it:\n\n.. code-block:: python\n\n   import ijson\n\n   @ijson.coroutine\n   def print_cities():\n      while True:\n         obj = (yield)\n         if obj['type'] != 'city':\n            continue\n         print(obj)\n\n   coro = ijson.items_coro(print_cities(), 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n   coro.close()\n\nAll four ijson iterators\nhave a ``*_coro`` counterpart\nthat work by pushing data into them.\nInstead of receiving a file-like object\nand option buffer size as arguments,\nthey receive a single ``target`` argument,\nwhich should be a coroutine-like object\n(anything implementing a ``send`` method)\nthrough which results will be published.\n\nAn alternative to providing a coroutine\nis to use ``ijson.sendable_list`` to accumulate results,\nproviding the list is cleared after each parsing iteration,\nlike this:\n\n.. code-block:: python\n\n   import ijson\n\n   events = ijson.sendable_list()\n   coro = ijson.items_coro(events, 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n      process_accumulated_events(events)\n      del events[:]\n   coro.close()\n   process_accumulated_events(events)\n\n\n.. _options:\n\nOptions\n=======\n\nAdditional options are supported by **all** ijson functions\nto give users more fine-grained control over certain operations:\n\n- The ``use_float`` option (defaults to ``False``)\n  controls how non-integer values are returned to the user.\n  If set to ``True`` users receive ``float()`` values;\n  otherwise ``Decimal`` values are constructed.\n  Note that building ``float`` values is usually faster,\n  but on the other hand there might be loss of precision\n  (which most applications will not care about)\n  and will raise an exception when overflow occurs\n  (e.g., if ``1e400`` is encountered).\n  This option also has the side-effect\n  that integer numbers bigger than ``2^64``\n  (but *sometimes* ``2^32``, see backends_)\n  will also raise an overflow error,\n  due to similar reasons.\n  Future versions of ijson\n  might change the default value of this option\n  to ``True``.\n- The ``multiple_values`` option (defaults to ``False``)\n  controls whether multiple top-level values are supported.\n  JSON content should contain a single top-level value\n  (see `the JSON Grammar <https://tools.ietf.org/html/rfc7159#section-2>`_).\n  However there are plenty of JSON files out in the wild\n  that contain multiple top-level values,\n  often separated by newlines.\n  By default ijson will fail to process these\n  with a ``parse error: trailing garbage`` error\n  unless ``multiple_values=True`` is specified.\n- Similarly the ``allow_comments`` option (defaults to ``False``)\n  controls whether C-style comments (e.g., ``/* a comment */``),\n  which are not supported by the JSON standard,\n  are allowed in the content or not.\n- For functions taking a file-like object,\n  an additional ``buf_size`` option (defaults to ``65536`` or 64KB)\n  specifies the amount of bytes the library\n  should attempt to read each time.\n- The ``items`` and ``kvitems`` functions, and all their variants,\n  have an optional ``map_type`` argument (defaults to ``dict``)\n  used to construct objects from the JSON stream.\n  This should be a dict-like type supporting item assignment.\n\n\nEvents\n======\n\nWhen using the lower-level ``ijson.parse`` function,\nthree-element tuples are generated\ncontaining a prefix, an event name, and a value.\nEvents will be one of the following:\n\n- ``start_map`` and ``end_map`` indicate\n  the beginning and end of a JSON object, respectively.\n  They carry a ``None`` as their value.\n- ``start_array`` and ``end_array`` indicate\n  the beginning and end of a JSON array, respectively.\n  They also carry a ``None`` as their value.\n- ``map_key`` indicates the name of a field in a JSON object.\n  Its associated value is the name itself.\n- ``null``, ``boolean``, ``integer``, ``double``, ``number`` and ``string``\n  all indicate actual content, which is stored in the associated value.\n\n\n.. _prefix:\n\nPrefix\n======\n\nA prefix represents the context within a JSON document\nwhere an event originates at.\nIt works as follows:\n\n- It starts as an empty string.\n- A ``<name>`` part is appended when the parser starts parsing the contents\n  of a JSON object member called ``name``,\n  and removed once the content finishes.\n- A literal ``item`` part is appended when the parser is parsing\n  elements of a JSON array,\n  and removed when the array ends.\n- Parts are separated by ``.``.\n\nWhen using the ``ijson.items`` function,\nthe prefix works as the selection\nfor which objects should be automatically built and returned by ijson.\n\n\n.. _backends:\n\nBackends\n========\n\nIjson provides several implementations of the actual parsing in the form of\nbackends located in ijson/backends:\n\n- ``yajl2_c``: a C extension using `YAJL <http://lloyd.github.io/yajl/>`__ 2.x.\n  This is the fastest, but *might* require a compiler and the YAJL development files\n  to be present when installing this package.\n  Binary wheel distributions exist for major platforms/architectures to spare users\n  from having to compile the package.\n- ``yajl2_cffi``: wrapper around `YAJL <http://lloyd.github.io/yajl/>`__ 2.x\n  using CFFI.\n- ``yajl2``: wrapper around YAJL 2.x using ctypes, for when you can't use CFFI\n  for some reason.\n- ``yajl``: deprecated YAJL 1.x + ctypes wrapper, for even older systems.\n- ``python``: pure Python parser, good to use with PyPy\n\nYou can import a specific backend and use it in the same way as the top level\nlibrary:\n\n.. code-block::  python\n\n    import ijson.backends.yajl2_cffi as ijson\n\n    for item in ijson.items(...):\n        # ...\n\nImporting the top level library as ``import ijson``\nuses the first available backend in the same order of the list above,\nand its name is recorded under ``ijson.backend``.\nIf the ``IJSON_BACKEND`` environment variable is set\nits value takes precedence and is used to select the default backend.\n\nYou can also use the ``ijson.get_backend`` function\nto get a specific backend based on a name:\n\n.. code-block:: python\n\n    backend = ijson.get_backend('yajl2_c')\n    for item in backend.items(...):\n        # ...\n\n\nPerformance tips\n================\n\nIn more-or-less decreasing order,\nthese are the most common actions you can take\nto ensure you get most of the performance\nout of ijson:\n\n- Make sure you use the fastest backend available.\n  See backends_ for details.\n- If you know your JSON data\n  contains only numbers that are \"well behaved\"\n  consider turning on the ``use_float`` option.\n  See options_ for details.\n- Make sure you feed ijson with binary data\n  instead of text data.\n  See faq_ #1 for details.\n- Play with the ``buf_size`` option,\n  as depending on your data source and your system\n  a value different from the default\n  might show better performance.\n  See options_ for details.\n\nThe benchmarking_ tool should help\nwith trying some of these options\nand observing their effect on your input files.\n\n\n.. _faq:\n\nFAQ\n===\n\n#. **Q**: Does ijson work with ``bytes`` or ``str`` values?\n\n   **A**: In short: both are accepted as input, outputs are only ``str``.\n\n   All ijson functions expecting a file-like object\n   should ideally be given one\n   that is opened in binary mode\n   (i.e., its ``read`` function returns ``bytes`` objects, not ``str``).\n   However if a text-mode file object is given\n   then the library will automatically\n   encode the strings into UTF-8 bytes.\n   A warning is currently issued (but not visible by default)\n   alerting users about this automatic conversion.\n\n   On the other hand ijson always returns text data\n   (JSON string values, object member names, event names, etc)\n   as ``str`` objects.\n   This mimics the behavior of the system ``json`` module.\n\n#. **Q**: How are numbers dealt with?\n\n   **A**: ijson returns ``int`` values for integers\n   and ``decimal.Decimal`` values for floating-point numbers.\n   This is mostly because of historical reasons.\n   Since 3.1 a new ``use_float`` option (defaults to ``False``)\n   is available to return ``float`` values instead.\n   See the options_ section for details.\n\n#. **Q**: I'm getting an ``UnicodeDecodeError``, or an ``IncompleteJSONError`` with no message\n\n   **A**: This error is caused by byte sequences that are not valid in UTF-8.\n   In other words, the data given to ijson is not *really* UTF-8 encoded,\n   or at least not properly.\n\n   Depending on where the data comes from you have different options:\n\n   * If you have control over the source of the data, fix it.\n\n   * If you have a way to intercept the data flow,\n     do so and pass it through a \"byte corrector\".\n     For instance, if you have a shell pipeline\n     feeding data through ``stdin`` into your process\n     you can add something like ``... | iconv -f utf8 -t utf8 -c | ...``\n     in between to correct invalid byte sequences.\n\n   * If you are working purely in python,\n     you can create a UTF-8 decoder\n     using codecs' `incrementaldecoder <https://docs.python.org/3/library/codecs.html#codecs.getincrementaldecoder>`_\n     to leniently decode your bytes into strings,\n     and feed those strings (using a file-like class) into ijson\n     (see our `string_reader_async internal class <https://github.com/ICRAR/ijson/blob/0157f3c65a7986970030d3faa75979ee205d3806/ijson/utils35.py#L19>`_\n     for some inspiration).\n\n   In the future ijson might offer something out of the box\n   to deal with invalid UTF-8 byte sequences.\n\n#. **Q**: I'm getting ``parse error: trailing garbage`` or ``Additional data found`` errors\n\n   **A**: This error signals that the input\n   contains more data than the top-level JSON value it's meant to contain.\n   This is *usually* caused by JSON data sources\n   containing multiple values, and is *usually* solved\n   by passing the ``multiple_values=True`` to the ijson function in use.\n   See the options_ section for details.\n\n#. **Q**: Are there any differences between the backends?\n\n   **A**: Apart from their performance,\n   all backends are designed to support the same capabilities.\n   There are however some small known differences:\n\n   * The ``yajl`` backend doesn't support ``multiple_values=True``.\n     It also doesn't complain about additional data\n     found after the end of the top-level JSON object.\n     When using ``use_float=True`` it also doesn't properly support\n     values greater than 2^32 in 32-bit platforms or Windows.\n     Numbers with leading zeros are not reported as invalid\n     (although they are invalid JSON numbers).\n     Incomplete JSON tokens at the end of an incomplete document\n     (e.g., ``{\"a\": fals``) are not reported as ``IncompleteJSONError``.\n\n   * The ``python`` backend doesn't support ``allow_comments=True``\n     It also internally works with ``str`` objects, not ``bytes``,\n     but this is an internal detail that users shouldn't need to worry about,\n     and might change in the future.\n\n\nAcknowledgements\n================\n\nijson was originally developed and actively maintained until 2016\nby `Ivan Sagalaev <http://softwaremaniacs.org/>`_.\nIn 2019 he\n`handed over <https://github.com/isagalaev/ijson/pull/58#issuecomment-500596815>`_\nthe maintenance of the project and the PyPI ownership.\n\nPython parser in ijson is relatively simple thanks to `Douglas Crockford\n<http://www.crockford.com/>`_ who invented a strict, easy to parse syntax.\n\nThe `YAJL <https://lloyd.github.io/yajl>`__ library by `Lloyd Hilaiel\n<http://lloyd.io/>`_ is the most popular and efficient way to parse JSON in an\niterative fashion.\n\nIjson was inspired by `yajl-py <http://pykler.github.com/yajl-py/>`_ wrapper by\n`Hatem Nassrat <http://www.nassrat.ca/>`_. Though ijson borrows almost nothing\nfrom the actual yajl-py code it was used as an example of integration with yajl\nusing ctypes.\n",
      "keywords": "",
      "platform": [],
      "classifiers": [
        "Development Status :: 5 - Production/Stable",
        "License :: OSI Approved :: BSD License",
        "Programming Language :: Python :: 3.5",
        "Programming Language :: Python :: 3.6",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Environment :: MetaData :: IBM Python Ecosystem"
      ],
      "download_url": "",
      "supported_platform": [],
      "comment": "",
      "provides": [],
      "requires": [],
      "obsoletes": [],
      "project_urls": [],
      "provides_dist": [],
      "obsoletes_dist": [],
      "requires_dist": [],
      "requires_external": [],
      "requires_python": "",
      "description_content_type": "text/x-rst",
      "provides_extras": [],
      "dynamic": [
        "author",
        "author-email",
        "classifier",
        "description",
        "description-content-type",
        "home-page",
        "license",
        "summary"
      ],
      "license_expression": "",
      "license_file": [
        "LICENSE.txt"
      ],
      "+links": [
        {
          "rel": "releasefile",
          "hash_spec": "sha256=6eed5d067263a559160ba03b83d7e67a18cbf34c26d801e1a32307f1511eeb65",
          "hashes": {
            "sha256": "6eed5d067263a559160ba03b83d7e67a18cbf34c26d801e1a32307f1511eeb65"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/6ee/d5d067263a559/ijson-3.3.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                32
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=7bab073e228417162fa8c14fb9e7149d6d6e9f10d0df7dfe5c73bcc40f2c8bc2",
          "hashes": {
            "sha256": "7bab073e228417162fa8c14fb9e7149d6d6e9f10d0df7dfe5c73bcc40f2c8bc2"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/7ba/b073e22841716/ijson-3.3.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                33
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=5cdf5dad913d14623582d4a091637f28ec504e4fb3176f153664fbc45e246f2d",
          "hashes": {
            "sha256": "5cdf5dad913d14623582d4a091637f28ec504e4fb3176f153664fbc45e246f2d"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/5cd/f5dad913d1462/ijson-3.3.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                33
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=de56060d7f763536eea8fd65fca4b7cc9c1239ec10a3132162b8ad417071bb92",
          "hashes": {
            "sha256": "de56060d7f763536eea8fd65fca4b7cc9c1239ec10a3132162b8ad417071bb92"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/de5/6060d7f763536/ijson-3.3.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                34
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=2adc43b2be54ae712a258eaaafd3ae82792d5a7f453fe901ea0c9ab9520294e9",
          "hashes": {
            "sha256": "2adc43b2be54ae712a258eaaafd3ae82792d5a7f453fe901ea0c9ab9520294e9"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/2ad/c43b2be54ae71/ijson-3.3.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                34
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=fd2e8421f5fc2859eb5e13d9281d77a4d13d7f15f2f54b1daf9d8928e1fc7cd6",
          "hashes": {
            "sha256": "fd2e8421f5fc2859eb5e13d9281d77a4d13d7f15f2f54b1daf9d8928e1fc7cd6"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/fd2/e8421f5fc2859/ijson-3.3.0-py3-none-any.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                7,
                27,
                12,
                44,
                34
              ],
              "dst": "ppc64le/linux"
            }
          ]
        }
      ]
    },
    "3.3.0+ppc64le1": {
      "name": "ijson",
      "version": "3.3.0+ppc64le1",
      "metadata_version": "2.2",
      "summary": "Iterative JSON parser with standard Python iterator interfaces",
      "home_page": "https://github.com/ICRAR/ijson",
      "author": "Rodrigo Tobar, Ivan Sagalaev",
      "author_email": "rtobar@icrar.org, maniac@softwaremaniacs.org",
      "maintainer": "",
      "maintainer_email": "",
      "license": "BSD",
      "description": ".. image:: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://github.com/ICRAR/ijson/actions/workflows/fast-built-and-test.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://coveralls.io/repos/github/ICRAR/ijson/badge.svg?branch=master\n    :target: https://coveralls.io/github/ICRAR/ijson?branch=master\n\n.. image:: https://badge.fury.io/py/ijson.svg\n    :target: https://badge.fury.io/py/ijson\n\n.. image:: https://img.shields.io/pypi/pyversions/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dd/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dw/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dm/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n\n=====\nijson\n=====\n\nIjson is an iterative JSON parser with standard Python iterator interfaces.\n\n.. contents::\n   :local:\n\n\nInstallation\n============\n\nIjson is hosted in PyPI, so you should be able to install it via ``pip``::\n\n  pip install ijson\n\nBinary wheels are provided\nfor major platforms\nand python versions.\nThese are built and published automatically\nusing `cibuildwheel <https://cibuildwheel.readthedocs.io/en/stable/>`_\nvia GitHub Actions.\n\n\nUsage\n=====\n\nAll usage example will be using a JSON document describing geographical\nobjects:\n\n.. code-block:: json\n\n    {\n      \"earth\": {\n        \"europe\": [\n          {\"name\": \"Paris\", \"type\": \"city\", \"info\": { ... }},\n          {\"name\": \"Thames\", \"type\": \"river\", \"info\": { ... }},\n          // ...\n        ],\n        \"america\": [\n          {\"name\": \"Texas\", \"type\": \"state\", \"info\": { ... }},\n          // ...\n        ]\n      }\n    }\n\n\nHigh-level interfaces\n---------------------\n\nMost common usage is having ijson yield native Python objects out of a JSON\nstream located under a prefix.\nThis is done using the ``items`` function.\nHere's how to process all European cities:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    objects = ijson.items(f, 'earth.europe.item')\n    cities = (o for o in objects if o['type'] == 'city')\n    for city in cities:\n        do_something_with(city)\n\nFor how to build a prefix see the prefix_ section below.\n\nOther times it might be useful to iterate over object members\nrather than objects themselves (e.g., when objects are too big).\nIn that case one can use the ``kvitems`` function instead:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    european_places = ijson.kvitems(f, 'earth.europe.item')\n    names = (v for k, v in european_places if k == 'name')\n    for name in names:\n        do_something_with(name)\n\n\nLower-level interfaces\n----------------------\n\nSometimes when dealing with a particularly large JSON payload it may worth to\nnot even construct individual Python objects and react on individual events\nimmediately producing some result.\nThis is achieved using the ``parse`` function:\n\n.. code-block::  python\n\n    import ijson\n\n    parser = ijson.parse(urlopen('http://.../'))\n    stream.write('<geo>')\n    for prefix, event, value in parser:\n        if (prefix, event) == ('earth', 'map_key'):\n            stream.write('<%s>' % value)\n            continent = value\n        elif prefix.endswith('.name'):\n            stream.write('<object name=\"%s\"/>' % value)\n        elif (prefix, event) == ('earth.%s' % continent, 'end_map'):\n            stream.write('</%s>' % continent)\n    stream.write('</geo>')\n\nEven more bare-bones is the ability to react on individual events\nwithout even calculating a prefix\nusing the ``basic_parse`` function:\n\n.. code-block:: python\n\n    import ijson\n\n    events = ijson.basic_parse(urlopen('http://.../'))\n    num_names = sum(1 for event, value in events\n                    if event == 'map_key' and value == 'name')\n\n\n.. _command_line:\n\nCommand line\n------------\n\nA command line utility is included with ijson\nto help visualise the output of each of the routines above.\nIt reads JSON from the standard input,\nand it prints the results of the parsing method chosen by the user\nto the standard output.\n\nThe tool is available by running the ``ijson.dump`` module.\nFor example::\n\n $> echo '{\"A\": 0, \"B\": [1, 2, 3, 4]}' | python -m ijson.dump -m parse\n #: path, name, value\n --------------------\n 0: , start_map, None\n 1: , map_key, A\n 2: A, number, 0\n 3: , map_key, B\n 4: B, start_array, None\n 5: B.item, number, 1\n 6: B.item, number, 2\n 7: B.item, number, 3\n 8: B.item, number, 4\n 9: B, end_array, None\n 10: , end_map, None\n\nUsing ``-h/--help`` will show all available options.\n\n\n.. _benchmarking:\n\nBenchmarking\n------------\n\nA command line utility is included with ijson\nto help benchmarking the different methods offered by the package.\nIt offers some built-in example inputs\nthat try to mimic different scenarios,\nbut more importantly it also supports user-provided inputs.\nYou can also specify which backends to time,\nnumber of iterations,\nand more.\n\nThe tool is available by running the ``ijson.benchmark`` module.\nFor example::\n\n $> python -m ijson.benchmark my/json/file.json -m items -p values.item\n\nUsing ``-h/--help`` will show all available options.\n\n\n``bytes``/``str`` support\n-------------------------\n\nAlthough not usually how they are meant to be run,\nall the functions above also accept\n``bytes`` and ``str`` objects\ndirectly as inputs.\nThese are then internally wrapped into a file object,\nand further processed.\nThis is useful for testing and prototyping,\nbut probably not extremely useful in real-life scenarios.\n\n\n``asyncio`` support\n-------------------\n\nAll of the methods above\nwork also on file-like asynchronous objects,\nso they can be iterated asynchronously.\nIn other words, something like this:\n\n.. code-block:: python\n\n   import asyncio\n   import ijson\n\n   async def run():\n      f = await async_urlopen('http://..../')\n      async for object in ijson.items(f, 'earth.europe.item'):\n         if object['type'] == 'city':\n            do_something_with(city)\n   asyncio.run(run())\n\nAn explicit set of ``*_async`` functions also exists\noffering the same functionality,\nexcept they will fail if anything other\nthan a file-like asynchronous object is given to them.\n(so the example above can also be written using ``ijson.items_async``).\nIn fact in ijson version 3.0\nthis was the only way to access\nthe ``asyncio`` support.\n\n\nIntercepting events\n-------------------\n\nThe four routines shown above\ninternally chain against each other:\ntuples generated by ``basic_parse``\nare the input for ``parse``,\nwhose results are the input to ``kvitems`` and ``items``.\n\nNormally users don't see this interaction,\nas they only care about the final output\nof the function they invoked,\nbut there are occasions when tapping\ninto this invocation chain this could be handy.\nThis is supported\nby passing the output of one function\n(i.e., an iterable of events, usually a generator)\nas the input of another,\nopening the door for user event filtering or injection.\n\nFor instance if one wants to skip some content\nbefore full item parsing:\n\n.. code-block:: python\n\n  import io\n  import ijson\n\n  parse_events = ijson.parse(io.BytesIO(b'[\"skip\", {\"a\": 1}, {\"b\": 2}, {\"c\": 3}]'))\n  while True:\n      prefix, event, value = next(parse_events)\n      if value == \"skip\":\n          break\n  for obj in ijson.items(parse_events, 'item'):\n      print(obj)\n\n\nNote that this interception\nonly makes sense for the ``basic_parse -> parse``,\n``parse -> items`` and ``parse -> kvitems`` interactions.\n\nNote also that event interception\nis currently not supported\nby the ``async`` functions.\n\n\nPush interfaces\n---------------\n\nAll examples above use a file-like object as the data input\n(both the normal case, and for ``asyncio`` support),\nand hence are \"pull\" interfaces,\nwith the library reading data as necessary.\nIf for whatever reason it's not possible to use such method,\nyou can still **push** data\nthrough yet a different interface: `coroutines <https://www.python.org/dev/peps/pep-0342/>`_\n(via generators, not ``asyncio`` coroutines).\nCoroutines effectively allow users\nto send data to them at any point in time,\nwith a final *target* coroutine-like object\nreceiving the results.\n\nIn the following example\nthe user is doing the reading\ninstead of letting the library do it:\n\n.. code-block:: python\n\n   import ijson\n\n   @ijson.coroutine\n   def print_cities():\n      while True:\n         obj = (yield)\n         if obj['type'] != 'city':\n            continue\n         print(obj)\n\n   coro = ijson.items_coro(print_cities(), 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n   coro.close()\n\nAll four ijson iterators\nhave a ``*_coro`` counterpart\nthat work by pushing data into them.\nInstead of receiving a file-like object\nand option buffer size as arguments,\nthey receive a single ``target`` argument,\nwhich should be a coroutine-like object\n(anything implementing a ``send`` method)\nthrough which results will be published.\n\nAn alternative to providing a coroutine\nis to use ``ijson.sendable_list`` to accumulate results,\nproviding the list is cleared after each parsing iteration,\nlike this:\n\n.. code-block:: python\n\n   import ijson\n\n   events = ijson.sendable_list()\n   coro = ijson.items_coro(events, 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n      process_accumulated_events(events)\n      del events[:]\n   coro.close()\n   process_accumulated_events(events)\n\n\n.. _options:\n\nOptions\n=======\n\nAdditional options are supported by **all** ijson functions\nto give users more fine-grained control over certain operations:\n\n- The ``use_float`` option (defaults to ``False``)\n  controls how non-integer values are returned to the user.\n  If set to ``True`` users receive ``float()`` values;\n  otherwise ``Decimal`` values are constructed.\n  Note that building ``float`` values is usually faster,\n  but on the other hand there might be loss of precision\n  (which most applications will not care about)\n  and will raise an exception when overflow occurs\n  (e.g., if ``1e400`` is encountered).\n  This option also has the side-effect\n  that integer numbers bigger than ``2^64``\n  (but *sometimes* ``2^32``, see backends_)\n  will also raise an overflow error,\n  due to similar reasons.\n  Future versions of ijson\n  might change the default value of this option\n  to ``True``.\n- The ``multiple_values`` option (defaults to ``False``)\n  controls whether multiple top-level values are supported.\n  JSON content should contain a single top-level value\n  (see `the JSON Grammar <https://tools.ietf.org/html/rfc7159#section-2>`_).\n  However there are plenty of JSON files out in the wild\n  that contain multiple top-level values,\n  often separated by newlines.\n  By default ijson will fail to process these\n  with a ``parse error: trailing garbage`` error\n  unless ``multiple_values=True`` is specified.\n- Similarly the ``allow_comments`` option (defaults to ``False``)\n  controls whether C-style comments (e.g., ``/* a comment */``),\n  which are not supported by the JSON standard,\n  are allowed in the content or not.\n- For functions taking a file-like object,\n  an additional ``buf_size`` option (defaults to ``65536`` or 64KB)\n  specifies the amount of bytes the library\n  should attempt to read each time.\n- The ``items`` and ``kvitems`` functions, and all their variants,\n  have an optional ``map_type`` argument (defaults to ``dict``)\n  used to construct objects from the JSON stream.\n  This should be a dict-like type supporting item assignment.\n\n\nEvents\n======\n\nWhen using the lower-level ``ijson.parse`` function,\nthree-element tuples are generated\ncontaining a prefix, an event name, and a value.\nEvents will be one of the following:\n\n- ``start_map`` and ``end_map`` indicate\n  the beginning and end of a JSON object, respectively.\n  They carry a ``None`` as their value.\n- ``start_array`` and ``end_array`` indicate\n  the beginning and end of a JSON array, respectively.\n  They also carry a ``None`` as their value.\n- ``map_key`` indicates the name of a field in a JSON object.\n  Its associated value is the name itself.\n- ``null``, ``boolean``, ``integer``, ``double``, ``number`` and ``string``\n  all indicate actual content, which is stored in the associated value.\n\n\n.. _prefix:\n\nPrefix\n======\n\nA prefix represents the context within a JSON document\nwhere an event originates at.\nIt works as follows:\n\n- It starts as an empty string.\n- A ``<name>`` part is appended when the parser starts parsing the contents\n  of a JSON object member called ``name``,\n  and removed once the content finishes.\n- A literal ``item`` part is appended when the parser is parsing\n  elements of a JSON array,\n  and removed when the array ends.\n- Parts are separated by ``.``.\n\nWhen using the ``ijson.items`` function,\nthe prefix works as the selection\nfor which objects should be automatically built and returned by ijson.\n\n\n.. _backends:\n\nBackends\n========\n\nIjson provides several implementations of the actual parsing in the form of\nbackends located in ijson/backends:\n\n- ``yajl2_c``: a C extension using `YAJL <http://lloyd.github.io/yajl/>`__ 2.x.\n  This is the fastest, but *might* require a compiler and the YAJL development files\n  to be present when installing this package.\n  Binary wheel distributions exist for major platforms/architectures to spare users\n  from having to compile the package.\n- ``yajl2_cffi``: wrapper around `YAJL <http://lloyd.github.io/yajl/>`__ 2.x\n  using CFFI.\n- ``yajl2``: wrapper around YAJL 2.x using ctypes, for when you can't use CFFI\n  for some reason.\n- ``yajl``: deprecated YAJL 1.x + ctypes wrapper, for even older systems.\n- ``python``: pure Python parser, good to use with PyPy\n\nYou can import a specific backend and use it in the same way as the top level\nlibrary:\n\n.. code-block::  python\n\n    import ijson.backends.yajl2_cffi as ijson\n\n    for item in ijson.items(...):\n        # ...\n\nImporting the top level library as ``import ijson``\nuses the first available backend in the same order of the list above,\nand its name is recorded under ``ijson.backend``.\nIf the ``IJSON_BACKEND`` environment variable is set\nits value takes precedence and is used to select the default backend.\n\nYou can also use the ``ijson.get_backend`` function\nto get a specific backend based on a name:\n\n.. code-block:: python\n\n    backend = ijson.get_backend('yajl2_c')\n    for item in backend.items(...):\n        # ...\n\n\nPerformance tips\n================\n\nIn more-or-less decreasing order,\nthese are the most common actions you can take\nto ensure you get most of the performance\nout of ijson:\n\n- Make sure you use the fastest backend available.\n  See backends_ for details.\n- If you know your JSON data\n  contains only numbers that are \"well behaved\"\n  consider turning on the ``use_float`` option.\n  See options_ for details.\n- Make sure you feed ijson with binary data\n  instead of text data.\n  See faq_ #1 for details.\n- Play with the ``buf_size`` option,\n  as depending on your data source and your system\n  a value different from the default\n  might show better performance.\n  See options_ for details.\n\nThe benchmarking_ tool should help\nwith trying some of these options\nand observing their effect on your input files.\n\n\n.. _faq:\n\nFAQ\n===\n\n#. **Q**: Does ijson work with ``bytes`` or ``str`` values?\n\n   **A**: In short: both are accepted as input, outputs are only ``str``.\n\n   All ijson functions expecting a file-like object\n   should ideally be given one\n   that is opened in binary mode\n   (i.e., its ``read`` function returns ``bytes`` objects, not ``str``).\n   However if a text-mode file object is given\n   then the library will automatically\n   encode the strings into UTF-8 bytes.\n   A warning is currently issued (but not visible by default)\n   alerting users about this automatic conversion.\n\n   On the other hand ijson always returns text data\n   (JSON string values, object member names, event names, etc)\n   as ``str`` objects.\n   This mimics the behavior of the system ``json`` module.\n\n#. **Q**: How are numbers dealt with?\n\n   **A**: ijson returns ``int`` values for integers\n   and ``decimal.Decimal`` values for floating-point numbers.\n   This is mostly because of historical reasons.\n   Since 3.1 a new ``use_float`` option (defaults to ``False``)\n   is available to return ``float`` values instead.\n   See the options_ section for details.\n\n#. **Q**: I'm getting an ``UnicodeDecodeError``, or an ``IncompleteJSONError`` with no message\n\n   **A**: This error is caused by byte sequences that are not valid in UTF-8.\n   In other words, the data given to ijson is not *really* UTF-8 encoded,\n   or at least not properly.\n\n   Depending on where the data comes from you have different options:\n\n   * If you have control over the source of the data, fix it.\n\n   * If you have a way to intercept the data flow,\n     do so and pass it through a \"byte corrector\".\n     For instance, if you have a shell pipeline\n     feeding data through ``stdin`` into your process\n     you can add something like ``... | iconv -f utf8 -t utf8 -c | ...``\n     in between to correct invalid byte sequences.\n\n   * If you are working purely in python,\n     you can create a UTF-8 decoder\n     using codecs' `incrementaldecoder <https://docs.python.org/3/library/codecs.html#codecs.getincrementaldecoder>`_\n     to leniently decode your bytes into strings,\n     and feed those strings (using a file-like class) into ijson\n     (see our `string_reader_async internal class <https://github.com/ICRAR/ijson/blob/0157f3c65a7986970030d3faa75979ee205d3806/ijson/utils35.py#L19>`_\n     for some inspiration).\n\n   In the future ijson might offer something out of the box\n   to deal with invalid UTF-8 byte sequences.\n\n#. **Q**: I'm getting ``parse error: trailing garbage`` or ``Additional data found`` errors\n\n   **A**: This error signals that the input\n   contains more data than the top-level JSON value it's meant to contain.\n   This is *usually* caused by JSON data sources\n   containing multiple values, and is *usually* solved\n   by passing the ``multiple_values=True`` to the ijson function in use.\n   See the options_ section for details.\n\n#. **Q**: Are there any differences between the backends?\n\n   **A**: Apart from their performance,\n   all backends are designed to support the same capabilities.\n   There are however some small known differences:\n\n   * The ``yajl`` backend doesn't support ``multiple_values=True``.\n     It also doesn't complain about additional data\n     found after the end of the top-level JSON object.\n     When using ``use_float=True`` it also doesn't properly support\n     values greater than 2^32 in 32-bit platforms or Windows.\n     Numbers with leading zeros are not reported as invalid\n     (although they are invalid JSON numbers).\n     Incomplete JSON tokens at the end of an incomplete document\n     (e.g., ``{\"a\": fals``) are not reported as ``IncompleteJSONError``.\n\n   * The ``python`` backend doesn't support ``allow_comments=True``\n     It also internally works with ``str`` objects, not ``bytes``,\n     but this is an internal detail that users shouldn't need to worry about,\n     and might change in the future.\n\n\nAcknowledgements\n================\n\nijson was originally developed and actively maintained until 2016\nby `Ivan Sagalaev <http://softwaremaniacs.org/>`_.\nIn 2019 he\n`handed over <https://github.com/isagalaev/ijson/pull/58#issuecomment-500596815>`_\nthe maintenance of the project and the PyPI ownership.\n\nPython parser in ijson is relatively simple thanks to `Douglas Crockford\n<http://www.crockford.com/>`_ who invented a strict, easy to parse syntax.\n\nThe `YAJL <https://lloyd.github.io/yajl>`__ library by `Lloyd Hilaiel\n<http://lloyd.io/>`_ is the most popular and efficient way to parse JSON in an\niterative fashion.\n\nIjson was inspired by `yajl-py <http://pykler.github.com/yajl-py/>`_ wrapper by\n`Hatem Nassrat <http://www.nassrat.ca/>`_. Though ijson borrows almost nothing\nfrom the actual yajl-py code it was used as an example of integration with yajl\nusing ctypes.\n",
      "keywords": "",
      "platform": [],
      "classifiers": [
        "Development Status :: 5 - Production/Stable",
        "License :: OSI Approved :: BSD License",
        "Programming Language :: Python :: 3.5",
        "Programming Language :: Python :: 3.6",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Environment :: MetaData :: IBM Python Ecosystem"
      ],
      "download_url": "",
      "supported_platform": [],
      "comment": "",
      "provides": [],
      "requires": [],
      "obsoletes": [],
      "project_urls": [],
      "provides_dist": [],
      "obsoletes_dist": [],
      "requires_dist": [],
      "requires_external": [],
      "requires_python": "",
      "description_content_type": "text/x-rst",
      "provides_extras": "",
      "dynamic": "summary",
      "license_expression": "",
      "license_file": "LICENSE.txt",
      "+links": [
        {
          "rel": "releasefile",
          "hash_spec": "sha256=01e62e570d3b4661ece06d2c07b637816af7f1cbb05f7d2692cd6733fafdb3fd",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/01e/62e570d3b4661/ijson-3.3.0+ppc64le1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                6
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=f057d344ab54a0155df9429b9cbffbdf07cd885710eca0d171dfd3931775faed",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/f05/7d344ab54a015/ijson-3.3.0+ppc64le1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                6
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=3d36cf1a55bb32717ad5f3afd34ba5865b4a43472573d1b871f1dedf0e9a9725",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/3d3/6cf1a55bb3271/ijson-3.3.0+ppc64le1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                7
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=db5608d1b4d9d21098cb8822980c3d64b484017fa6adc9da01018cf31bc4af31",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/db5/608d1b4d9d210/ijson-3.3.0+ppc64le1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                7
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=11c553789c0913a465a5a51bfe4eba44fafaa05b6f99e7d0a0d563dbfbf97564",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/11c/553789c0913a4/ijson-3.3.0+ppc64le1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                8
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=e1e5b9e2054587f91a48795daad9a35bb69b5e73262f4df62fd414c3ddaef035",
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/e1e/5b9e2054587f9/ijson-3.3.0+ppc64le1-py3-none-any.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                3,
                16,
                9,
                21,
                8
              ],
              "dst": "ppc64le/linux"
            }
          ]
        }
      ]
    },
    "3.5.0+ppc64le1": {
      "name": "ijson",
      "version": "3.5.0+ppc64le1",
      "metadata_version": "2.4",
      "summary": "Iterative JSON parser with standard Python iterator interfaces",
      "home_page": "",
      "author": "",
      "author_email": "Rodrigo Tobar <rtobar@icrar.org>, Ivan Sagalaev <maniac@softwaremaniacs.org>",
      "maintainer": "",
      "maintainer_email": "",
      "license": "",
      "description": ".. image:: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://github.com/ICRAR/ijson/actions/workflows/fast-built-and-test.yml/badge.svg\n    :target: https://github.com/ICRAR/ijson/actions/workflows/deploy-to-pypi.yml\n\n.. image:: https://coveralls.io/repos/github/ICRAR/ijson/badge.svg?branch=master\n    :target: https://coveralls.io/github/ICRAR/ijson?branch=master\n\n.. image:: https://badge.fury.io/py/ijson.svg\n    :target: https://badge.fury.io/py/ijson\n\n.. image:: https://img.shields.io/pypi/pyversions/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dd/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dw/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n.. image:: https://img.shields.io/pypi/dm/ijson.svg\n    :target: https://pypi.python.org/pypi/ijson\n\n\n=====\nijson\n=====\n\nIjson is an iterative JSON parser with standard Python iterator interfaces.\n\n.. contents::\n   :local:\n\n\nInstallation\n============\n\nIjson is hosted in PyPI, so you should be able to install it via ``pip``::\n\n  pip install ijson\n\nBinary wheels are provided\nfor major platforms\nand python versions.\nThese are built and published automatically\nusing `cibuildwheel <https://cibuildwheel.readthedocs.io/en/stable/>`_\nvia GitHub Actions.\n\n\nUsage\n=====\n\nAll usage example will be using a JSON document describing geographical\nobjects:\n\n.. code-block:: json\n\n    {\n      \"earth\": {\n        \"europe\": [\n          {\"name\": \"Paris\", \"type\": \"city\", \"info\": { ... }},\n          {\"name\": \"Thames\", \"type\": \"river\", \"info\": { ... }},\n          // ...\n        ],\n        \"america\": [\n          {\"name\": \"Texas\", \"type\": \"state\", \"info\": { ... }},\n          // ...\n        ]\n      }\n    }\n\n\nHigh-level interfaces\n---------------------\n\nijson works by continuously reading data from a JSON stream provided by the user.\nThis is presented as a file-like object.\nIn particular it must provide a ``read(size)`` method\nreturning either ``bytes`` (preferably) or ``str``.\nExample file-like objects are\nfiles opened with ``open``,\nHTTP/HTTPS requests made using ``urllib.request.urlopen``,\n``socket.socket`` objects,\nand more.\n\nThe most common usage of ijson is to yield native Python objects\nlocated under a prefix.\nThis is done using the ``items`` function.\nHere's how to process all European cities:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    objects = ijson.items(f, 'earth.europe.item')\n    cities = (o for o in objects if o['type'] == 'city')\n    for city in cities:\n        do_something_with(city)\n\nFor how to build a prefix see the prefix_ section below.\n\nOther times it might be useful to iterate over object members\nrather than objects themselves (e.g., when objects are too big).\nIn that case one can use the ``kvitems`` function instead:\n\n.. code-block::  python\n\n    import ijson\n\n    f = urlopen('http://.../')\n    european_places = ijson.kvitems(f, 'earth.europe.item')\n    names = (v for k, v in european_places if k == 'name')\n    for name in names:\n        do_something_with(name)\n\n\nLower-level interfaces\n----------------------\n\nSometimes when dealing with a particularly large JSON payload it may worth to\nnot even construct individual Python objects and react on individual events\nimmediately producing some result.\nThis is achieved using the ``parse`` function:\n\n.. code-block::  python\n\n    import ijson\n\n    parser = ijson.parse(urlopen('http://.../'))\n    stream.write('<geo>')\n    for prefix, event, value in parser:\n        if (prefix, event) == ('earth', 'map_key'):\n            stream.write('<%s>' % value)\n            continent = value\n        elif prefix.endswith('.name'):\n            stream.write('<object name=\"%s\"/>' % value)\n        elif (prefix, event) == ('earth.%s' % continent, 'end_map'):\n            stream.write('</%s>' % continent)\n    stream.write('</geo>')\n\nEven more bare-bones is the ability to react on individual events\nwithout even calculating a prefix\nusing the ``basic_parse`` function:\n\n.. code-block:: python\n\n    import ijson\n\n    events = ijson.basic_parse(urlopen('http://.../'))\n    num_names = sum(1 for event, value in events\n                    if event == 'map_key' and value == 'name')\n\n\nCommand line\n------------\n\nA command line utility is included with ijson\nto help visualise the output of each of the routines above.\nIt reads JSON from the standard input,\nand it prints the results of the parsing method chosen by the user\nto the standard output.\n\nThe tool is available by running the ``ijson.dump`` module.\nFor example::\n\n $> echo '{\"A\": 0, \"B\": [1, 2, 3, 4]}' | python -m ijson.dump -m parse\n #: path, name, value\n --------------------\n 0: , start_map, None\n 1: , map_key, A\n 2: A, number, 0\n 3: , map_key, B\n 4: B, start_array, None\n 5: B.item, number, 1\n 6: B.item, number, 2\n 7: B.item, number, 3\n 8: B.item, number, 4\n 9: B, end_array, None\n 10: , end_map, None\n\nUsing ``-h/--help`` will show all available options.\n\n\nBenchmarking\n------------\n\nA command line utility is included with ijson\nto help benchmarking the different methods offered by the package.\nIt offers some built-in example inputs\nthat try to mimic different scenarios,\nbut more importantly it also supports user-provided inputs.\nYou can also specify which backends to time,\nnumber of iterations,\nand more.\n\nThe tool is available by running the ``ijson.benchmark`` module.\nFor example::\n\n $> python -m ijson.benchmark my/json/file.json -m items -p values.item\n\nUsing ``-h/--help`` will show all available options.\n\n\n``bytes``/``str`` support\n-------------------------\n\nAlthough not usually how they are meant to be run,\nall the functions above also accept\n``bytes`` and ``str`` objects\ndirectly as inputs.\nThese are then internally wrapped into a file object,\nand further processed.\nThis is useful for testing and prototyping,\nbut probably not extremely useful in real-life scenarios.\n\n\nIterator support\n----------------\n\nIn many situations the direct input users want to pass to ijson\nis an iterator (e.g., a generator) rather than a file-like object.\nijson provides a built-in adapter to bridge this gap:\n\n- ``ijson.from_iter(iterable_or_async_iterable_of_bytes)``\n\n\n``asyncio`` support\n-------------------\n\nAll of the methods above\nwork also on file-like asynchronous objects,\nso they can be iterated asynchronously.\nIn other words, something like this:\n\n.. code-block:: python\n\n   import asyncio\n   import ijson\n\n   async def run():\n      f = await async_urlopen('http://..../')\n      async for object in ijson.items(f, 'earth.europe.item'):\n         if object['type'] == 'city':\n            do_something_with(city)\n   asyncio.run(run())\n\nAn explicit set of ``*_async`` functions also exists\noffering the same functionality,\nexcept they will fail if anything other\nthan a file-like asynchronous object is given to them.\n(so the example above can also be written using ``ijson.items_async``).\nIn fact in ijson version 3.0\nthis was the only way to access\nthe ``asyncio`` support.\n\n\nIntercepting events\n-------------------\n\nThe four routines shown above\ninternally chain against each other:\ntuples generated by ``basic_parse``\nare the input for ``parse``,\nwhose results are the input to ``kvitems`` and ``items``.\n\nNormally users don't see this interaction,\nas they only care about the final output\nof the function they invoked,\nbut there are occasions when tapping\ninto this invocation chain this could be handy.\nThis is supported\nby passing the output of one function\n(i.e., an iterable of events, usually a generator)\nas the input of another,\nopening the door for user event filtering or injection.\n\nFor instance if one wants to skip some content\nbefore full item parsing:\n\n.. code-block:: python\n\n  import io\n  import ijson\n\n  parse_events = ijson.parse(io.BytesIO(b'[\"skip\", {\"a\": 1}, {\"b\": 2}, {\"c\": 3}]'))\n  while True:\n      prefix, event, value = next(parse_events)\n      if value == \"skip\":\n          break\n  for obj in ijson.items(parse_events, 'item'):\n      print(obj)\n\n\nNote that this interception\nonly makes sense for the ``basic_parse -> parse``,\n``parse -> items`` and ``parse -> kvitems`` interactions.\n\nNote also that event interception\nis currently not supported\nby the ``async`` functions.\n\n\nPush interfaces\n---------------\n\nAll examples above use a file-like object as the data input\n(both the normal case, and for ``asyncio`` support),\nand hence are \"pull\" interfaces,\nwith the library reading data as necessary.\nIf for whatever reason it's not possible to use such method,\nyou can still **push** data\nthrough yet a different interface: `coroutines <https://www.python.org/dev/peps/pep-0342/>`_\n(via generators, not ``asyncio`` coroutines).\nCoroutines effectively allow users\nto send data to them at any point in time,\nwith a final *target* coroutine-like object\nreceiving the results.\n\nIn the following example\nthe user is doing the reading\ninstead of letting the library do it:\n\n.. code-block:: python\n\n   import ijson\n\n   @ijson.coroutine\n   def print_cities():\n      while True:\n         obj = (yield)\n         if obj['type'] != 'city':\n            continue\n         print(obj)\n\n   coro = ijson.items_coro(print_cities(), 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n   coro.close()\n\nAll four ijson iterators\nhave a ``*_coro`` counterpart\nthat work by pushing data into them.\nInstead of receiving a file-like object\nand option buffer size as arguments,\nthey receive a single ``target`` argument,\nwhich should be a coroutine-like object\n(anything implementing a ``send`` method)\nthrough which results will be published.\n\nAn alternative to providing a coroutine\nis to use ``ijson.sendable_list`` to accumulate results,\nproviding the list is cleared after each parsing iteration,\nlike this:\n\n.. code-block:: python\n\n   import ijson\n\n   events = ijson.sendable_list()\n   coro = ijson.items_coro(events, 'earth.europe.item')\n   f = urlopen('http://.../')\n   for chunk in iter(functools.partial(f.read, buf_size)):\n      coro.send(chunk)\n      process_accumulated_events(events)\n      del events[:]\n   coro.close()\n   process_accumulated_events(events)\n\n\nOptions\n=======\n\nAdditional options are supported by **all** ijson functions\nto give users more fine-grained control over certain operations:\n\n- The ``use_float`` option (defaults to ``False``)\n  controls how non-integer values are returned to the user.\n  If set to ``True`` users receive ``float()`` values;\n  otherwise ``Decimal`` values are constructed.\n  Note that building ``float`` values is usually faster,\n  but on the other hand there might be loss of precision\n  (which most applications will not care about)\n  and will raise an exception when overflow occurs\n  (e.g., if ``1e400`` is encountered).\n  This option also has the side-effect\n  that integer numbers bigger than ``2^64``\n  (but *sometimes* ``2^32``, see capabilities_)\n  will also raise an overflow error,\n  due to similar reasons.\n  Future versions of ijson\n  might change the default value of this option\n  to ``True``.\n- The ``multiple_values`` option (defaults to ``False``)\n  controls whether multiple top-level values are supported.\n  JSON content should contain a single top-level value\n  (see `the JSON Grammar <https://tools.ietf.org/html/rfc7159#section-2>`_).\n  However there are plenty of JSON files out in the wild\n  that contain multiple top-level values,\n  often separated by newlines.\n  By default ijson will fail to process these\n  with a ``parse error: trailing garbage`` error\n  unless ``multiple_values=True`` is specified.\n- Similarly the ``allow_comments`` option (defaults to ``False``)\n  controls whether C-style comments (e.g., ``/* a comment */``),\n  which are not supported by the JSON standard,\n  are allowed in the content or not.\n- For functions taking a file-like object,\n  an additional ``buf_size`` option (defaults to ``65536`` or 64KB)\n  specifies the amount of bytes the library\n  should attempt to read each time.\n- The ``items`` and ``kvitems`` functions, and all their variants,\n  have an optional ``map_type`` argument (defaults to ``dict``)\n  used to construct objects from the JSON stream.\n  This should be a dict-like type supporting item assignment.\n\n\nEvents\n======\n\nWhen using the lower-level ``ijson.parse`` function,\nthree-element tuples are generated\ncontaining a prefix, an event name, and a value.\nEvents will be one of the following:\n\n- ``start_map`` and ``end_map`` indicate\n  the beginning and end of a JSON object, respectively.\n  They carry a ``None`` as their value.\n- ``start_array`` and ``end_array`` indicate\n  the beginning and end of a JSON array, respectively.\n  They also carry a ``None`` as their value.\n- ``map_key`` indicates the name of a field in a JSON object.\n  Its associated value is the name itself.\n- ``null``, ``boolean``, ``integer``, ``double``, ``number`` and ``string``\n  all indicate actual content, which is stored in the associated value.\n\n\nPrefix\n======\n\nA prefix represents the context within a JSON document\nwhere an event originates at.\nIt works as follows:\n\n- It starts as an empty string.\n- A ``<name>`` part is appended when the parser starts parsing the contents\n  of a JSON object member called ``name``,\n  and removed once the content finishes.\n- A literal ``item`` part is appended when the parser is parsing\n  elements of a JSON array,\n  and removed when the array ends.\n- Parts are separated by ``.``.\n\nWhen using the ``ijson.items`` function,\nthe prefix works as the selection\nfor which objects should be automatically built and returned by ijson.\n\n\nBackends\n========\n\nIjson provides several implementations of the actual parsing in the form of\nbackends located in ijson/backends:\n\n- ``yajl2_c``: a C extension using `YAJL <http://lloyd.github.io/yajl/>`__ 2.x.\n  This is the fastest, but *might* require a compiler and the YAJL development files\n  to be present when installing this package.\n  Binary wheel distributions exist for major platforms/architectures to spare users\n  from having to compile the package.\n- ``yajl2_cffi``: wrapper around `YAJL <http://lloyd.github.io/yajl/>`__ 2.x\n  using CFFI.\n- ``yajl2``: wrapper around YAJL 2.x using ctypes, for when you can't use CFFI\n  for some reason.\n- ``yajl``: deprecated YAJL 1.x + ctypes wrapper, for even older systems.\n- ``python``: pure Python parser, good to use with PyPy\n\nThis list of backend names is available under the ``ijson.ALL_BACKENDS`` constant.\n\nYou can import a specific backend and use it in the same way as the top level\nlibrary:\n\n.. code-block::  python\n\n    import ijson.backends.yajl2_cffi as ijson\n\n    for item in ijson.items(...):\n        # ...\n\nImporting the top level library as ``import ijson``\nuses the first available backend in the same order of the list above,\nand its name is recorded under ``ijson.backend``.\nIf the ``IJSON_BACKEND`` environment variable is set\nits value takes precedence and is used to select the default backend.\n\nYou can also use the ``ijson.get_backend`` function\nto get a specific backend based on a name:\n\n.. code-block:: python\n\n    backend = ijson.get_backend('yajl2_c')\n    for item in backend.items(...):\n        # ...\n\n\nCapabilities\n------------\n\nApart from their performance,\nall backends are designed to support the same capabilities.\nThere are however some small known differences,\nall of which can be queried by inspecting\nthe ``capabilities`` module constant.\nIt contains the following members:\n\n* ``c_comments``: C-style comments are supported.\n* ``multiple_values``: multiple top-level JSON values are supported.\n* ``detects_invalid_leading_zeros``: numbers with leading zeroes\n  are reported as invalid (as they should, as pert the JSON standard),\n  raising a ``ValueError``.\n* ``detects_incomplete_json_tokens``: detects incomplete JSON tokens\n  at the end of an incomplete document (e.g., ``{\"a\": fals``),\n  raising an ``IncompleteJSONError``.\n* ``int64``: when using ``use_float=True``,\n    values greater than or equal to ``2^32`` are correctly returned.\n\nThese capabilities are supported by all backends,\nwith the following exceptions:\n\n* The ``yajl`` backend doesn't support ``multiple_values``,\n  ``detects_invalid_leading_zeros`` and ``detects_incomplete_json_tokens``.\n  It also doesn't support ``int64``\n  in platforms with a 32-bit C ``long`` type.\n\n* The ``python`` backend doesn't support ``c_comments``.\n\n\nPerformance tips\n================\n\nIn more-or-less decreasing order,\nthese are the most common actions you can take\nto ensure you get most of the performance\nout of ijson:\n\n- Make sure you use the fastest backend available.\n  See backends_ for details.\n- If you know your JSON data\n  contains only numbers that are \"well behaved\"\n  consider turning on the ``use_float`` option.\n  See options_ for details.\n- Make sure you feed ijson with binary data\n  instead of text data.\n  See faq_ #1 for details.\n- Play with the ``buf_size`` option,\n  as depending on your data source and your system\n  a value different from the default\n  might show better performance.\n  See options_ for details.\n\nThe benchmarking_ tool should help\nwith trying some of these options\nand observing their effect on your input files.\n\n\nFAQ\n===\n\n#. **Q**: Does ijson work with ``bytes`` or ``str`` values?\n\n   **A**: In short: both are accepted as input, outputs are only ``str``.\n\n   All ijson functions expecting a file-like object\n   should ideally be given one\n   that is opened in binary mode\n   (i.e., its ``read`` function returns ``bytes`` objects, not ``str``).\n   However if a text-mode file object is given\n   then the library will automatically\n   encode the strings into UTF-8 bytes.\n   A warning is currently issued (but not visible by default)\n   alerting users about this automatic conversion.\n\n   On the other hand ijson always returns text data\n   (JSON string values, object member names, event names, etc)\n   as ``str`` objects.\n   This mimics the behavior of the system ``json`` module.\n\n#. **Q**: How are numbers dealt with?\n\n   **A**: ijson returns ``int`` values for integers\n   and ``decimal.Decimal`` values for floating-point numbers.\n   This is mostly because of historical reasons.\n   Since 3.1 a new ``use_float`` option (defaults to ``False``)\n   is available to return ``float`` values instead.\n   See the options_ section for details.\n\n#. **Q**: I'm getting an ``UnicodeDecodeError``, or an ``IncompleteJSONError`` with no message\n\n   **A**: This error is caused by byte sequences that are not valid in UTF-8.\n   In other words, the data given to ijson is not *really* UTF-8 encoded,\n   or at least not properly.\n\n   Depending on where the data comes from you have different options:\n\n   * If you have control over the source of the data, fix it.\n\n   * If you have a way to intercept the data flow,\n     do so and pass it through a \"byte corrector\".\n     For instance, if you have a shell pipeline\n     feeding data through ``stdin`` into your process\n     you can add something like ``... | iconv -f utf8 -t utf8 -c | ...``\n     in between to correct invalid byte sequences.\n\n   * If you are working purely in python,\n     you can create a UTF-8 decoder\n     using codecs' `incrementaldecoder <https://docs.python.org/3/library/codecs.html#codecs.getincrementaldecoder>`_\n     to leniently decode your bytes into strings,\n     and feed those strings (using a file-like class) into ijson\n     (see our `string_reader_async internal class <https://github.com/ICRAR/ijson/blob/0157f3c65a7986970030d3faa75979ee205d3806/ijson/utils35.py#L19>`_\n     for some inspiration).\n\n   In the future ijson might offer something out of the box\n   to deal with invalid UTF-8 byte sequences.\n\n#. **Q**: I'm getting ``parse error: trailing garbage`` or ``Additional data found`` errors\n\n   **A**: This error signals that the input\n   contains more data than the top-level JSON value it's meant to contain.\n   This is *usually* caused by JSON data sources\n   containing multiple values, and is *usually* solved\n   by passing the ``multiple_values=True`` to the ijson function in use.\n   See the options_ section for details.\n\n#. **Q**: How do I use ijson with ``requests`` or ``httpx``\n\n   **A**: The ``requests`` library downloads the body of the HTTP response immediately by default.\n   To stream JSON into ijson, pass ``stream=True`` and adapt the byte iterator:\n\n   .. code-block:: python\n\n      import requests\n      import ijson\n\n      with requests.get('https://..', stream=True) as resp:\n          resp.raise_for_status()\n          f = ijson.from_iter(resp.iter_content(chunk_size=64*1024))\n          objects = ijson.items(f, 'earth.europe.item')\n          cities = (o for o in objects if o['type'] == 'city')\n          for city in cities:\n            do_something_with(city)\n\n   You can also pass ``Response.raw`` directly (it's a file-like object),\n   but using ``iter_content`` is preferred because ``requests`` will transparently\n   handle HTTP transfer encodings (e.g., gzip, chunked).\n\n\n   For async usage with ``httpx``:\n\n   .. code-block:: python\n\n      import httpx\n      import ijson\n\n      async with httpx.AsyncClient() as client:\n          async with client.stream('GET', 'https://..') as resp:\n              resp.raise_for_status()\n              f = ijson.from_iter(resp.aiter_bytes())\n              objects = ijson.items(f, 'earth.europe.item')\n              cities = (o async for o in objects if o['type'] == 'city')\n              async for city in cities:\n                do_something_with(city)\n\n\nAcknowledgements\n================\n\nijson was originally developed and actively maintained until 2016\nby `Ivan Sagalaev <http://softwaremaniacs.org/>`_.\nIn 2019 he\n`handed over <https://github.com/isagalaev/ijson/pull/58#issuecomment-500596815>`_\nthe maintenance of the project and the PyPI ownership.\n\nPython parser in ijson is relatively simple thanks to `Douglas Crockford\n<http://www.crockford.com/>`_ who invented a strict, easy to parse syntax.\n\nThe `YAJL <https://lloyd.github.io/yajl>`__ library by `Lloyd Hilaiel\n<http://lloyd.io/>`_ is the most popular and efficient way to parse JSON in an\niterative fashion.\nWhen building the library ourselves,\nwe use `our own fork <https://github.com/rtobar/yajl>`__\nthat contains fixes for all known CVEs.\n\nIjson was inspired by `yajl-py <http://pykler.github.com/yajl-py/>`_ wrapper by\n`Hatem Nassrat <http://www.nassrat.ca/>`_. Though ijson borrows almost nothing\nfrom the actual yajl-py code it was used as an example of integration with yajl\nusing ctypes.\n",
      "keywords": "",
      "platform": [],
      "classifiers": [
        "Development Status :: 5 - Production/Stable",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Programming Language :: Python :: 3.13",
        "Programming Language :: Python :: 3.14",
        "Programming Language :: Python :: Implementation :: CPython",
        "Programming Language :: Python :: Implementation :: PyPy",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Environment :: MetaData :: IBM Python Ecosystem"
      ],
      "download_url": "",
      "supported_platform": [],
      "comment": "",
      "provides": [],
      "requires": [],
      "obsoletes": [],
      "project_urls": [
        "Homepage, https://github.com/ICRAR/ijson"
      ],
      "provides_dist": [],
      "obsoletes_dist": [],
      "requires_dist": [],
      "requires_external": [],
      "requires_python": ">=3.9",
      "description_content_type": "text/x-rst",
      "provides_extras": [],
      "dynamic": [
        "license-file"
      ],
      "license_expression": "BSD-3-Clause AND ISC",
      "license_file": [
        "LICENSE.txt"
      ],
      "+links": [
        {
          "rel": "releasefile",
          "hash_spec": "sha256=885f59ad56700a8dd877318e06da25fa03b3a7d5c1931190ca57ffb723ad4b87",
          "hashes": {
            "sha256": "885f59ad56700a8dd877318e06da25fa03b3a7d5c1931190ca57ffb723ad4b87"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/885/f59ad56700a8d/ijson-3.5.0+ppc64le1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                5,
                11,
                11,
                43,
                18
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=f0671cb2bb5746ed18b27612440be22674f98b7d0d36d384a8aacd17b419e9af",
          "hashes": {
            "sha256": "f0671cb2bb5746ed18b27612440be22674f98b7d0d36d384a8aacd17b419e9af"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/f06/71cb2bb5746ed/ijson-3.5.0+ppc64le1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                5,
                11,
                11,
                43,
                18
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=78ea3a62d785fa172ea9969e7306cf77fcbf70aa29a8191ba5864be374a452ee",
          "hashes": {
            "sha256": "78ea3a62d785fa172ea9969e7306cf77fcbf70aa29a8191ba5864be374a452ee"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/78e/a3a62d785fa17/ijson-3.5.0+ppc64le1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                5,
                11,
                11,
                43,
                19
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=4c5db1faf2d1706b0c125bb9ac9513566ae48b2cda536a634bf69456522abe94",
          "hashes": {
            "sha256": "4c5db1faf2d1706b0c125bb9ac9513566ae48b2cda536a634bf69456522abe94"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/4c5/db1faf2d1706b/ijson-3.5.0+ppc64le1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                5,
                11,
                11,
                43,
                19
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=74a34c762b0b310a87bf1abba8a1a4fecff0adb3f649e53270e25b69ec5f7160",
          "hashes": {
            "sha256": "74a34c762b0b310a87bf1abba8a1a4fecff0adb3f649e53270e25b69ec5f7160"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/74a/34c762b0b310a/ijson-3.5.0+ppc64le1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                5,
                11,
                11,
                43,
                20
              ],
              "dst": "ppc64le/linux"
            }
          ]
        },
        {
          "rel": "releasefile",
          "hash_spec": "sha256=f8763081d477c05ca62986158347643ec1ddb149294841133352172597dc065e",
          "hashes": {
            "sha256": "f8763081d477c05ca62986158347643ec1ddb149294841133352172597dc065e"
          },
          "href": "https://wheels.developerfirst.ibm.com/ppc64le/linux/+f/f87/63081d477c05c/ijson-3.5.0+ppc64le1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl",
          "log": [
            {
              "what": "upload",
              "who": "ppc64le",
              "when": [
                2026,
                5,
                11,
                11,
                43,
                20
              ],
              "dst": "ppc64le/linux"
            }
          ]
        }
      ]
    }
  },
  "type": "projectconfig"
}
