Converting JSON to XML (espectially orders object)

My code depends on receiving data in XML format. It looks like the REST service no longer supports that. Would their happen to be a good conversion tool out there to convert the orders JSON object to XML? We can worry about other JSON objects later, assuming I need them converted.

My current Python code doesn’t do the conversion correctly - it doesn’t handle lists correctly, which makes since because how could a generic conversion tool know that each element in the orders JSON object is an order object. I am sort of hoping someone else already hit this problem and found a good solution.

There are lots of examples out there for converting XML to JSON, just not the other direction.

Thanks.

1 Like

2 ideas (one might be good long term, but not sure I can do it short term):

  1. Use ShopifyAPI python library here.
  2. Since I know what XML tags I care about and support in my code, my crazy and quicker idea is to go through the JSON object. If I see the key is for a list and ends in “s”, then the XML pattern will be <key with 's'><key without 's'>...</key without 's'><key without 's'>...</key without 's'><key without 's'>...</key without 's'><key without 's'>...</key without 's'></key with 's'>. Yes, there are probably scenarios that little trick won’t work, but short term it might give me some breathing room.
    Any pitfalls with either idea? And is there a tool out there that provides a better and quicker solution?

Hey @Anthony_Baldarelli, I think your best approach here would be to use the python library, but switch to Graphql at the same time https://github.com/Shopify/shopify_python_api?tab=readme-ov-file#graphql.

This way instead of trying to convert the entire order object you can instead just query the specific fields your system requires (I realize this talk of Graphql may be getting repetitive after our last conversation)

Short term, can’t hurt to run some tests to see of your second idea works though.

Curious to see if there are other ideas from the community!

Finally found a trick here, using dicttoxml python module.
Here is some example code:

    with open( inputJsonFile ) as fd:
            jsonDict = json.load(fd)
            fd.close();
    xml = None
    dom = None
    if( not( jsonDict == None )):
        #xml = xmltodict.unparse(jsonDict, pretty=True, full_document=False)
        #xml = dicttoxml(jsonDict, root=False, return_bytes=False)
        my_item_func = lambda x: x[:-1]
        xml = dicttoxml(jsonDict, return_bytes=False, item_func=my_item_func)
        if( not( xml == None )):
            xml = xml.replace("<root>", "")
            xml = xml.replace("</root>", "")
            dom = parseString(xml)

Then, if I want the pretty version, I use print( dom.toprettyxml(), file=sys.stdout ). If don’t want the pretty version, I use print( xml, file=sys.stdout ). Some things to point out:

  1. I remove the root tag because the dicttoxml module uses that by default. I could have used root=False, but that seemed messier. Was just easier to do it this way.
  2. I had to use return_bytes=False because, by default, it wraps the string with b'<XML>...</XML>', for a byte string (I guess, I did not research that part).
  3. I used my_item_func to tell dicttoxml to replace the default item tag for list items with the same tag as the root tag, minus the trailing “s”.
    What I found out is that the xmltodict module, which I originally used and revealed my problem, did not allow such fine tuned control. It would have worked for the simplest JSON variants, but not with more complex versions.

BTW, I am not entirely sure ShopifyAPI actually creates a nice Order Python object. I think it just gets a JSON string, in which case I would have to use some idea like the above anyway, but I have not had time to try it yet. That is on my to-do list, long term.

Minor update to above (6/17/2025):
First time using Python lambas, so I missed some opportunities. I could have written my_item_func = lambda parent: parent[:-1] if parent[-1] == 's' else parent + "_item" instead of my_item_func = lambda x: x[:-1]. This would prevent some outliers. I am not worrying about that in my case, but someone else might find the idea helpful.

1 Like