Issue converting JSON arrays when using JSON to XML Policy

Not applicable

Hello,

I'm having some trouble properly converting JSON arrays to equivalent XML arrays using the JSON to XML policy. The JSON object used in the request is as follows:

{
  "message": {
    "returnMsg": "Data processed successfully",
    "returnCode": 0
  },
  "recipientGroups": [
    {
      "id": 11,
      "name": "Test Group 1",
      "description": "Test Group 1 Description",
      "recipientGroupSites": []
    },
    {
      "id": 12,
      "name": "Test Group 1",
      "description": "Test Group 1 Description",
      "recipientGroupSites": []
    },
    {
      "id": 13,
      "name": "Test Group 1",
      "description": "Test Group 1 Description",
      "recipientGroupSites": []
    }
  ]
}

The resulting XML is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<cpc>
    <message>
        <returnMsg>Data processed successfully</returnMsg>
        <returnCode>0</returnCode>
    </message>
    <recipientGroups>
        <id>11</id>
        <name>Test Group 1</name>
        <description>Test Group 1 Description</description>
    </recipientGroups>
    <recipientGroups>
        <id>12</id>
        <name>Test Group 1</name>
        <description>Test Group 1 Description</description>
    </recipientGroups>
    <recipientGroups>
        <id>13</id>
        <name>Test Group 1</name>
        <description>Test Group 1 Description</description>
    </recipientGroups>
</cpc>

What I would like to achieve is XML of the following form

<?xml version="1.0" encoding="UTF-8"?>
<cpc>
    <message>
        <returnMsg>Data processed successfully</returnMsg>
        <returnCode>0</returnCode>
    </message>
    <recipientGroups>
        <recipientGroup>
            <id>11</id>
            <name>Test Group 1</name>
            <description>Test Group 1 Description</description>
        </recipientGroup>
        <recipientGroup>
            <id>12</id>
            <name>Test Group 1</name>
            <description>Test Group 1 Description</description>
        </recipientGroup>
        <recipientGroup>
            <id>13</id>
            <name>Test Group 1</name>
            <description>Test Group 1 Description</description>
        </recipientGroup>
    </recipientGroups>
</cpc>

The JSON to XML policy options I use are as follows:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JSONToXML async="false" continueOnError="false" enabled="true" name="JSON-to-XML-1">
    <DisplayName>JSON to XML</DisplayName>
    <Properties/>
    <Options>
        <NullValue>NULL</NullValue>
        <NamespaceBlockName>#namespaces</NamespaceBlockName>
        <DefaultNamespaceNodeName>$default</DefaultNamespaceNodeName>
        <NamespaceSeparator>:</NamespaceSeparator>
        <TextNodeName>#text</TextNodeName>
        <AttributePrefix>$</AttributePrefix>
        <InvalidCharsReplacement>_</InvalidCharsReplacement>
        <ObjectRootElementName>cpc</ObjectRootElementName>
        <ArrayRootElementName>Array</ArrayRootElementName>
        <ArrayItemElementName>Item</ArrayItemElementName>
    </Options>
    <OutputVariable>response</OutputVariable>
    <Source>response</Source>
</JSONToXML>

I've also tried replacing the ArrayRootElement and ArrayItemElement to recipientGroups and recipientGroup respectively. For some reason this doesn't change the resulting XML in any way.

Was wondering if anyone could provide any insight into this.

Thanks,

Brad Sheppard

Solved Solved
2 3 5,259
1 ACCEPTED SOLUTION

Let me have a look....

I understand the question. I tried what you described and got the same results. I'm going to look into it a little more deeply. But just for a quick response - if I were doing this and didn't want to get stuck on it, I would use either:

  • a JSON-to-JSON conversion implemented in JavaScript prior to the JSON-to-XML, to convert the elements of the array in question (recipientGroups) to wrapped hashes.
  • an XSLT after the JSON-to-XML to accomplish the analogous thing

For the former, you want to produce this:

"recipientGroups": [
    { "recipientGroup" : {
      "id": 11,
      "name": "Test Group 1",
      "description": "Test Group 1 Description",
      "recipientGroupSites": []
    } } ,

To do this, the JavaScript looks like this:

// json-to-json.js
// ------------------------------------------------------------------
//
var c = JSON.parse(context.getVariable('request.content'));
if (c.recipientGroups) {
  c.recipientGroups = c.recipientGroups.map(function(item){
    return { recipientGroup : item };
  });
  context.setVariable('request.content', JSON.stringify(c));
}

I looked into the policy a bit further and the configuration options you are using, ArrayRootElementName, and etc ..., are designed to be used when the JSON is an array. In that case there needs to be a root element name, to apply to the resulting document. So I'd say maybe there is a misunderstanding on how that configuration option works, and possibly the documentation is unclear or incorrect on that.

But the bottom line is that the JSON-to-XML policy will not inject names for arrays that occur at arbitrary points in the input JSON.

A JSON-to-JSON conversion, plus the JSON-to-XML, would do what you want, though. Or, a JSON-to-XML, with a succeeding XSLT.

View solution in original post

3 REPLIES 3

Let me have a look....

I understand the question. I tried what you described and got the same results. I'm going to look into it a little more deeply. But just for a quick response - if I were doing this and didn't want to get stuck on it, I would use either:

  • a JSON-to-JSON conversion implemented in JavaScript prior to the JSON-to-XML, to convert the elements of the array in question (recipientGroups) to wrapped hashes.
  • an XSLT after the JSON-to-XML to accomplish the analogous thing

For the former, you want to produce this:

"recipientGroups": [
    { "recipientGroup" : {
      "id": 11,
      "name": "Test Group 1",
      "description": "Test Group 1 Description",
      "recipientGroupSites": []
    } } ,

To do this, the JavaScript looks like this:

// json-to-json.js
// ------------------------------------------------------------------
//
var c = JSON.parse(context.getVariable('request.content'));
if (c.recipientGroups) {
  c.recipientGroups = c.recipientGroups.map(function(item){
    return { recipientGroup : item };
  });
  context.setVariable('request.content', JSON.stringify(c));
}

I looked into the policy a bit further and the configuration options you are using, ArrayRootElementName, and etc ..., are designed to be used when the JSON is an array. In that case there needs to be a root element name, to apply to the resulting document. So I'd say maybe there is a misunderstanding on how that configuration option works, and possibly the documentation is unclear or incorrect on that.

But the bottom line is that the JSON-to-XML policy will not inject names for arrays that occur at arbitrary points in the input JSON.

A JSON-to-JSON conversion, plus the JSON-to-XML, would do what you want, though. Or, a JSON-to-XML, with a succeeding XSLT.

Hi Dino,

Thank you for your response. I'll use the JSON-to-JSON conversion you mentioned in the meantime. I suspect there's some sort of bug in the JSONtoXML policy, as the documentation on the policy suggests the XML shouldn't be as it is. If I find a more elegant solution, or manage to resolve the issue, I'll comment it here.

Thanks again,

Brad

@Dino Is there any solution available for the issue yet ?