Here with the help of XSDATA and json file input I have generated Model class. I am passing the JSON to a method for getting converted as Model. Below are the files code. sample.xml
<?xml version="1.0"?>
<catalog>
<books>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
</books>
</catalog>
XML file converted to JSON sample.json
{
"catalog": {
"books": {
"book": [
{
"@id": "bk101",
"author": "Gambardella, Matthew",
"title": "XML Developer's Guide",
"genre": "Computer",
"price": "44.95",
"publish_date": "2000-10-01",
"description": "An in-depth look at creating applications \n with XML."
},
{
"@id": "bk101",
"author": "Gambardella, Matthew",
"title": "XML Developer's Guide",
"genre": "Computer",
"price": "44.95",
"publish_date": "2000-10-01",
"description": "An in-depth look at creating applications \n with XML."
}
]
}
}
}
models.py
from dataclasses import dataclass, field
from typing import List, Optional
from xsdata.models.datatype import XmlDate
@dataclass
class Book:
class Meta:
name = "book"
id: Optional[str] = field(
default=None,
metadata={
"name": "@id",
"type": "Element",
}
)
author: Optional[str] = field(
default=None,
metadata={
"type": "Element",
}
)
title: Optional[str] = field(
default=None,
metadata={
"type": "Element",
}
)
genre: Optional[str] = field(
default=None,
metadata={
"type": "Element",
}
)
price: Optional[float] = field(
default=None,
metadata={
"type": "Element",
}
)
publish_date: Optional[XmlDate] = field(
default=None,
metadata={
"type": "Element",
}
)
description: Optional[str] = field(
default=None,
metadata={
"type": "Element",
}
)
@dataclass
class Books:
class Meta:
name = "books"
book: List[Book] = field(
default_factory=list,
metadata={
"type": "Element",
}
)
@dataclass
class Catalog:
class Meta:
name = "catalog"
books: Optional[Books] = field(
default=None,
metadata={
"type": "Element",
}
)
@dataclass
class Models:
class Meta:
name = "models"
catalog: Optional[Catalog] = field(
default=None,
metadata={
"type": "Element",
}
)
model_con.py
import logging
import sys
import json
from xsdata.formats.dataclass.context import XmlContext
from xsdata.formats.dataclass.parsers import JsonParser
from xsdata.formats.dataclass.parsers.config import ParserConfig
from models.models import Models
from xml_to_json import XmlToJson
class Utilities:
@staticmethod
def json_to_model(metadata_json: str) -> Models:
logger = logging.getLogger(__name__)
logger.info('%s: Converting JSON to model', sys._getframe().f_code.co_name)
context: XmlContext = XmlContext()
config = ParserConfig(fail_on_unknown_attributes=False, fail_on_unknown_properties=False)
parser: JsonParser = JsonParser(context=context, config=config)
extract_model: Models = parser.from_string(metadata_json, Models)
return extract_model
if __name__ == "__main__":
extract_meta_path = r"C:\XSDATA\sample.xml"
xtj = XmlToJson()
xtj.xml_file_name = extract_meta_path
# print(xtj.json_data)
ut = Utilities()
md = ut.json_to_model(metadata_json=xtj.json_data)
print(md)
For one "book" value inside "books" the model is unable to fetch the value, while for more than one "book" it is able to return that value inside model. Below I have attached an example: sample.json -> with only one book
{
"catalog": {
"books": {
"book": {
"@id": "bk101",
"author": "Gambardella, Matthew",
"title": "XML Developer's Guide",
"genre": "Computer",
"price": "44.95",
"publish_date": "2000-10-01",
"description": "An in-depth look at creating applications \n with XML."
}
}
}
}
Model Generated: Models(catalog=Catalog(books=Books(book=[])))
And above sample.json file contains multiple book inside books the model generated is:
Models(catalog=Catalog(books=Books(book=[Book(id='bk101', author='Gambardella, Matthew', title="XML Developer's Guide", genre='Computer', price=44.95, publish_date=XmlDate(2000, 10, 1), description='An in-depth look at creating applications \n with XML.'), Book(id='bk101', author='Gambardella, Matthew', title="XML Developer's Guide", genre='Computer', price=44.95, publish_date=XmlDate(2000, 10, 1), description='An in-depth look at creating applications \n with XML.')])))
I am unable to understand for value inside books, why is the model unable to fetch the values while for multiple book inside books the List[Book] is working fine? Apart from it what can be the change I can make to Models class to handle this error?