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)