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)