============ JSON Binding ============ All binding modules rely on a :class:`~xsdata.formats.dataclass.context.XmlContext` instance to cache model metadata and binding information. It's recommended to either reuse the same parser/serializer instance or reuse the context instance. .. code-block:: from xsdata.formats.dataclass.context import XmlContext from xsdata.formats.dataclass.parsers import JsonParser from xsdata.formats.dataclass.serializers import JsonSerializer context = XmlContext() parser = JsonParser(context=context) serializer = JsonSerializer(context=context) .. testsetup:: * import io from pathlib import Path from xsdata.formats.dataclass.context import XmlContext from xsdata.formats.dataclass.parsers import JsonParser from xsdata.models.datatype import XmlDate from tests import fixtures_dir from tests.fixtures.books.books import Books Parse from json filename ======================== .. doctest:: >>> from pathlib import Path >>> from xsdata.formats.dataclass.context import XmlContext >>> from xsdata.formats.dataclass.parsers import JsonParser >>> from tests.fixtures.books.books import Books >>> from tests import fixtures_dir # pathlib.Path ... >>> filename = str(fixtures_dir.joinpath("books/books.json")) >>> parser = JsonParser(context=XmlContext()) >>> books = parser.parse(filename, Books) >>> books.book[0] BookForm(author='Hightower, Kim', title='The First Book', genre='Fiction', price=44.95, pub_date=XmlDate(2000, 10, 1), review='An amazing story of nothing.', id='bk001', lang='en') Parse from json file object =========================== .. doctest:: >>> json_path = fixtures_dir.joinpath("books/books.json") >>> with json_path.open("rb") as fp: ... books = parser.parse(fp, Books) >>> books.book[0] BookForm(author='Hightower, Kim', title='The First Book', genre='Fiction', price=44.95, pub_date=XmlDate(2000, 10, 1), review='An amazing story of nothing.', id='bk001', lang='en') Parse from json stream ====================== .. doctest:: >>> import io >>> books = parser.parse(io.BytesIO(json_path.read_bytes()), Books) >>> books.book[0] BookForm(author='Hightower, Kim', title='The First Book', genre='Fiction', price=44.95, pub_date=XmlDate(2000, 10, 1), review='An amazing story of nothing.', id='bk001', lang='en') Parse from json string ====================== .. doctest:: >>> books = parser.from_string(json_path.read_text(), Books) >>> books.book[0] BookForm(author='Hightower, Kim', title='The First Book', genre='Fiction', price=44.95, pub_date=XmlDate(2000, 10, 1), review='An amazing story of nothing.', id='bk001', lang='en') Parse from json bytes ===================== .. doctest:: >>> books = parser.from_bytes(json_path.read_bytes(), Books) >>> books.book[0] BookForm(author='Hightower, Kim', title='The First Book', genre='Fiction', price=44.95, pub_date=XmlDate(2000, 10, 1), review='An amazing story of nothing.', id='bk001', lang='en') Parse from json Path ==================== .. doctest:: >>> books = parser.from_path(json_path, Books) >>> books.book[0] BookForm(author='Hightower, Kim', title='The First Book', genre='Fiction', price=44.95, pub_date=XmlDate(2000, 10, 1), review='An amazing story of nothing.', id='bk001', lang='en') Parse json with unknown properties ================================== By default the parser will fail on unknown properties, but you can disable these errors through configuration. .. doctest:: >>> from tests.fixtures.books import * # Import all classes >>> from xsdata.formats.dataclass.parsers.config import ParserConfig ... >>> config = ParserConfig( ... fail_on_unknown_properties=False, ... ) >>> json_string = """{ ... "author": "Hightower, Kim", ... "unknown_property": "I will fail" ... }""" >>> parser = JsonParser(config=config) >>> parser.from_string(json_string, BookForm) BookForm(author='Hightower, Kim', title=None, genre=None, price=None, pub_date=None, review=None, id=None, lang='en') API :ref:`Reference `. Parse with unknown json target type =================================== It's optimal to provide the target model but completely optional. The parser can scan all the imported modules to find a matching dataclass. .. doctest:: >>> from tests.fixtures.books import * # Import all classes >>> json_string = """{ ... "author": "Hightower, Kim", ... "title": "The First Book", ... "genre": "Fiction", ... "price": 44.95, ... "pub_date": "2000-10-01", ... "review": "An amazing story of nothing.", ... "id": "bk001" ... }""" >>> parser = JsonParser() >>> parser.from_string(json_string) BookForm(author='Hightower, Kim', title='The First Book', genre='Fiction', price=44.95, pub_date=XmlDate(2000, 10, 1), review='An amazing story of nothing.', id='bk001', lang='en') .. warning:: The class locator searches for a dataclass that includes all the input object properties. This process doesn't work for documents with unknown properties even if the configuration option is disabled! Parser list of objects ====================== Specify the target binding type to ``List[ModelName]`` .. doctest:: >>> from typing import List >>> >>> json_string = """[ ... { ... "author": "Hightower, Kim", ... "title": "The First Book", ... "genre": "Fiction", ... "price": 44.95, ... "pub_date": "2000-10-01", ... "review": "An amazing story of nothing.", ... "id": "bk001" ... }, ... { ... "author": "Nagata, Suanne", ... "title": "Becoming Somebody", ... "genre": "Biography", ... "price": null, ... "pub_date": null, ... "review": "A masterpiece of the fine art of gossiping.", ... "id": "bk002" ... } ... ]""" >>> parser = JsonParser() >>> booklist = parser.from_string(json_string, List[BookForm]) >>> booklist[1].author 'Nagata, Suanne' Parser with custom json load factory ==================================== The default factory is python's builtin :func:`python:json.load` but you can use any other implementation as long as it's has a compatible signature. .. code-block:: python import ujson parser = JsonParser(load_factory=ujson.load) Serialize json to string ======================== .. doctest:: >>> from xsdata.formats.dataclass.context import XmlContext >>> from xsdata.formats.dataclass.serializers import JsonSerializer >>> from xsdata.formats.dataclass.serializers.config import SerializerConfig >>> from xsdata.models.datatype import XmlDate >>> books = Books( ... book=[ ... BookForm( ... id="bk001", ... author="Hightower, Kim", ... title="The First Book", ... genre="Fiction", ... price=44.95, ... review="An amazing story of nothing.", ... ), ... BookForm( ... id="bk002", ... author="Nagata, Suanne", ... title="Becoming Somebody", ... price=33.95, ... pub_date=XmlDate(2001, 1, 10), ... review="A masterpiece of the fine art of gossiping.", ... ), ... ] ... ) >>> config = SerializerConfig(pretty_print=True) >>> serializer = JsonSerializer(context=XmlContext(), config=config) >>> print(serializer.render(books)) { "book": [ { "author": "Hightower, Kim", "title": "The First Book", "genre": "Fiction", "price": 44.95, "pub_date": null, "review": "An amazing story of nothing.", "id": "bk001", "lang": "en" }, { "author": "Nagata, Suanne", "title": "Becoming Somebody", "genre": null, "price": 33.95, "pub_date": "2001-01-10", "review": "A masterpiece of the fine art of gossiping.", "id": "bk002", "lang": "en" } ] } Serialize json to stream ========================= .. doctest:: >>> from pathlib import Path ... >>> path = Path("output.json") >>> with path.open("w") as fp: ... serializer.write(fp, books) ... >>> print(path.read_text()) { "book": [ { "author": "Hightower, Kim", "title": "The First Book", "genre": "Fiction", "price": 44.95, "pub_date": null, "review": "An amazing story of nothing.", "id": "bk001", "lang": "en" }, { "author": "Nagata, Suanne", "title": "Becoming Somebody", "genre": null, "price": 33.95, "pub_date": "2001-01-10", "review": "A masterpiece of the fine art of gossiping.", "id": "bk002", "lang": "en" } ] } >>> path.unlink() Serialize with custom dict factory ================================== By using a custom dict factory you can change the output behaviour, like filter out ``None`` values. .. doctest:: >>> from typing import Dict, Tuple >>> >>> def filter_none(x: Tuple) -> Dict: ... return {k: v for k, v in x if v is not None} >>> >>> books.book[0].genre = None >>> config = SerializerConfig(pretty_print=True) >>> serializer = JsonSerializer(dict_factory=filter_none, config=config) >>> print(serializer.render(books.book[0])) { "author": "Hightower, Kim", "title": "The First Book", "price": 44.95, "review": "An amazing story of nothing.", "id": "bk001", "lang": "en" } or conveniently .. doctest:: >>> from xsdata.formats.dataclass.serializers.json import DictFactory >>> >>> serializer = JsonSerializer(dict_factory=DictFactory.FILTER_NONE) Serialize with custom json dump factory ======================================= The default factory is python's builtin :func:`python:json.dump` but you can use any other implementation as long as it's has a compatible signature. .. code-block:: python import ujson serializer = JsonSerializer(dump_factory=ujson.dump) .. meta:: :keywords: json, parse, serialize, python