# JSON Binding

All binding modules rely on a `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.

    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)

## Parse from json filename

    >>> 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

    >>> 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

    >>> 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

    >>> 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

    >>> 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

    >>> 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.

    >>> from tests.fixtures.books import *  # Import all classes
    >>> from xsdata.formats.dataclass.parsers.config import ParserConfig
    ...
    >>> config = ParserConfig(
    ...     fail_on_unknown_properties=False,
    ...     fail_on_unknown_attributes=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 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.

    >>> 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]`

    >>> 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 `json.load()` but you can use any other implementation as long as it’s has a compatible signature.

    import ujson

    parser = JsonParser(load_factory=ujson.load)

## Serialize json to string

    >>> 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

    >>> 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.

    >>> 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

    >>> 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 `json.dump()` but you can use any other implementation as long as it’s has a compatible signature.

    import ujson

    serializer = JsonSerializer(dump_factory=ujson.dump)