0

My Python scripts converts the xml to json. But the array of an for e.g address is converted to an object which I don't want. I want it to remain as array only. Below is my python script along with input xml and output json I am expecting. Thanks and appreciate your help In our application we take xml as an input string in a variable and also output json in a variable and test and compare the xml with the json

import json
import xmltodict

xml = xmltodict.parse(inputxml)
CustomerCreateandUpdate = xml['SyncCustomerCreateandUpdate']['DataArea']['CustomerCreateandUpdate']
outputjson = json.dumps(CustomerCreateandUpdate)

<?xml version="1.0" encoding="UTF-8"?>
<SyncCustomerCreateandUpdate xmlns="http://schema.infor.com/InforOAGIS/2" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" languageCode="EN" releaseID="9.2" 
systemEnvironmentCode="Production" versionID="2.11.0">
<ApplicationArea>
    <Sender>
        <LogicalID schemeVersionID="16.0.0.015">lid://infor.m3.m3</LogicalID>
        <ComponentID schemeVersionID="16.0.0.20201209170022">M3BE</ComponentID>
        <ConfirmationCode>OnError</ConfirmationCode>
    </Sender>
    <CreationDateTime>2021-03-04T12:33:12.487Z</CreationDateTime>
    <BODID>1bb40f80-8039-4264-b903-fa58ca2d3a9a</BODID>
</ApplicationArea>
<DataArea>
    <Sync>
        <AccountingEntityID>001_090</AccountingEntityID>
        <ActionCriteria>
            <ActionExpression actionCode="Add"/>
        </ActionCriteria>
    </Sync>
    <CustomerCreateandUpdate>
        <customerName>TEST1838</customerName>
        <customerStatus>Test5</customerStatus>
        <addresses>
            <addressLine1>test</addressLine1>
            <addressLine2>test</addressLine2>
            <addressLine3>test</addressLine3>
            <addressLine4>test</addressLine4>
            <postalCode>2200</postalCode>
            <city>Herentals</city>
            <stateCode>test</stateCode>
            <countryCode>BE</countryCode>
        </addresses>
        <phones>
            <phoneNumber>test</phoneNumber>
        </phones>
        <faxNumber>999</faxNumber>
        <contacts>
            <firstName>test</firstName>
            <lastName>test</lastName>
            <emailAddress>test</emailAddress>
            <mobilePhone>test</mobilePhone>
        </contacts>
        <emails>
            <emailType>TEST</emailType>
            <emailAddress>Test</emailAddress>
        </emails>
        <references>test</references>
        <freeFields>
            <number>0</number>
            <content>test</content>
        </freeFields>
        <searchKey>test</searchKey>
        <customerType>test</customerType>
        <description>test</description>
        <serviceArea>test</serviceArea>
        <lelyCenter>test</lelyCenter>
        <lspId>test</lspId>
        <m3Id>test</m3Id>
        <createdById>test</createdById>
        <lastModifiedById>test</lastModifiedById>
        <lastModifiedDate>test</lastModifiedDate>
        <vatNumber>test</vatNumber>
    </CustomerCreateandUpdate>
</DataArea>
Json expected output:

{
"customerName": "",
"customerStatus": "",
"addresses": [
{
  "addressLine1": "",
  "addressLine2": "",
  "addressLine3": "",
  "addressLine4": "",
  "postalCode": "",
  "city": "",
  "stateCode": "",
  "countryCode": ""
  }
   ],
  "phones": [
  {
  "phoneNumber": ""
  }
  ],
  "faxNumber": "",
 "contacts": [
  {
  "firstName": "",
  "lastName": "",
  "emailAddress": "",
  "mobilePhone": ""
   }
   ],
  "emails": [
   {
   "emailType": "",
   "emailAddress": ""
   }
   ],
  "references": [
  ""
  ],
  "freeFields": [
  {
  "number": 0,
  "content": ""
  }
   ],
 "language": "",
 "searchKey": "",
 "customerType": 0,
 "description": "",
 "lelyCenter": "",
 "lspId": "",
 "m3Id": "",
 "createdById": "",
 "lastModifiedById": "",
 "lastModifiedDate": "",
 "vatNumber": ""
 }
1
  • One comment my arrays have issue only when there is one set of data. It gives output as an object in json. But when multiple addresses or phones then no issues Commented Mar 12, 2021 at 12:55

1 Answer 1

1

The way address data is described in your xml drives xmltodict to represent it as a json object. First, address data sould be encapsulated into a dedicated container like so (How to represent list data in XML):

  <addresses>

    <address>
      <addressLine1>test</addressLine1>
      <addressLine2>test</addressLine2>
      <addressLine3>test</addressLine3>
      <addressLine4>test</addressLine4>
      <postalCode>2200</postalCode>
      <city>Herentals</city>
      <stateCode>test</stateCode>
      <countryCode>BE</countryCode>
    </address>

  </addresses>

But obviously this structure is not enough for xmltodict to detect it as a list of items. It needs to browse at least to times the same tag to understand it as an iterable. So if your address list has only one element you have to put a void address tag:

  <addresses>

    <address>
      <addressLine1>test</addressLine1>
      <addressLine2>test</addressLine2>
      <addressLine3>test</addressLine3>
      <addressLine4>test</addressLine4>
      <postalCode>2200</postalCode>
      <city>Herentals</city>
      <stateCode>test</stateCode>
      <countryCode>BE</countryCode>
    </address>

    <address></address>
    
  </addresses>

EDIT

With the new version of xmltodict it is not necessary to add a void tag. Just use the argument force_list={<tag name>} in the parse method (xmltodict does not return a list for one element):

xmltodict.parse(xml_data, force_list={"addresses"})
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your reply. But my json output required for third party has that structure. So only if main addresses tag comes twice then it works. I need to agree with the customer if we can have a void address tag inside main addresses tag
Hi , Thank you very much along with addresses i also added phones to the force method it gave both addresses and phones in array format. One more question I want to remove the tags CustomerCreateandUpdate, dataarea etc but json.dumps use only one argument any other option is there? output_json=json.dumps(json_j) #outputjson = json.dumps(CustomerCreateandUpdate)
Just build another dictionary alongside the one you got after json conversion, and push only key/value pairs that you need. For example: clean_json = { "addresses": output_json["DataArea"]["CustomerCreateandUpdate"]["addresses"] }
My issue is resolved now. I have also added the arrays I wanted to the force method and removed the xml tags which were coming in json. Thank you very much for your time and help. Much appreciated. Happy friday and have a nice weekend

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.