Karan Garg
Karan Garg

Reputation: 33

JSON to XML conversion without changing the sequence

I am using the below code to convert json to xml of multiple XML files with different JSON structures.

String toXmlRequest = fullRequest.toString();               
JSONObject jsonObj = new JSONObject(toXmlRequest);              
String XmlRequest = XML.toString(jsonObj);
System.out.println(XmlRequest);

Input

     {
      "EnrollmentRequest":
        {
          "data": 
            {
              "commonDataContext":
                   {
                      "requestId": "ADA12131",
                      "clientId": "ABCDEF",
                      "timestamp":"2013-12-13T11:10:00.715-05:00"
                   },
               "cardNumber" : "123456789012345" ,
               "firstName" : "John" ,
               "lastName" : "Smith" ,
               "email" : "[email protected]" ,
               "enrollStatus" : "E" , 
               "pathEnroll" : "NewAcct",
               "cardSavedIndicator" : "Y"
          }
        }
     }

Output

      <EnrollmentRequest>
          <data>
              <firstName>John</firstName>
              <lastName>Smith</lastName>
              <commonDataContext>
                    <clientId>ABCDEF</clientId>
                    <requestId>ADA12131</requestId>
                    <timestamp>2013-12-13T11:10:00.715-05:00</timestamp>
              </commonDataContext>
              <pathEnroll>NewAcct</pathEnroll>
              <enrollStatus>E</enrollStatus>
              <cardSavedIndicator>Y</cardSavedIndicator>
              <cardNumber>123456789012345</cardNumber>
              <email>[email protected]</email>
          </data>
      </EnrollmentRequest>

The sequence of the output is getting changed. It is not able to keep the actual sequence. Is there any way this can be kept intact.

Upvotes: 3

Views: 3143

Answers (2)

Abhishek Muskawad
Abhishek Muskawad

Reputation: 1

For embedded json arrays, you need to apply one more condition to check if it array and return it as json array.

if(nested.isArray()) {
            JSONArray arr = new JSONArray();
            for(JsonNode value : nested){
                arr.put(value.asText());
            }
            return arr;
        }

Upvotes: 0

Adam
Adam

Reputation: 36723

This is not possible using org.json.JSONObject directly. The reason is that JSONObject uses an internal store of type HashMap. HashMap does not preserve insertion order

It would be possible with a LinkedHashMap, however it does not appear possible to configure JSONObject to use one.

/**
 * Construct an empty JSONObject.
 */
public JSONObject() {
    this.map = new HashMap<String, Object>();
}

An alternative would be to read using a library that does preserve order, e.g. Jackson....

ObjectMapper mapper = new ObjectMapper();
JsonNode jackson = mapper.readTree(fullRequest);

and then feed that into XML

String xmlRequest = XML.toString(new JSONAdapter(jackson));

with the necessary type adaption to make the Jackson object look like a org.json.JSONObject. Incomplete example below:

private static class JSONAdapter extends JSONObject {

    private JsonNode jackson;

    public JSONAdapter(JsonNode jackson) {
        this.jackson = jackson;
    }

    @Override
    public Iterator<String> keys() {
        return jackson.fieldNames();
    }

    @Override
    public Object opt(String key) {
        return get(key);
    }

    @Override
    public Object get(String key) throws JSONException {
        JsonNode nested = jackson.get(key);
        if (nested.isObject()) {
            return new JSONAdapter(nested);
        } else if (nested.isTextual()) {
            return nested.asText();
        } else if (nested.isNumber()) {
            return nested.asDouble();
        } else if (nested.isBoolean()) {
            return nested.asBoolean();
        }
        return null;
    }

}

Output

<EnrollmentRequest>
    <data>
        <commonDataContext>
            <requestId>ADA12131</requestId>
            <clientId>ABCDEF</clientId>
            <timestamp>2013-12-13T11:10:00.715-05:00</timestamp>
        </commonDataContext>
        <cardNumber>123456789012345</cardNumber>
        <firstName>John</firstName>
        <lastName>Smith</lastName>
        <email>[email protected]</email>
        <enrollStatus>E</enrollStatus>
        <pathEnroll>NewAcct</pathEnroll>
        <cardSavedIndicator>Y</cardSavedIndicator>
    </data>
</EnrollmentRequest>

Upvotes: 1

Related Questions