0

I am currently trying to find a way to validate if my JSON object has another object in it or an array while using liquid templates.

I am using the xml-to-json policy which takes my below xml and turns it into JSON

  <additional-data-set>
    <additional-data>
      <name>LodgementDate</name>
      <value>24/04/2019 00:00:00 NZST</value>
    </additional-data>
  </additional-data-set>

Converted to JSON

"additional-data": {
        "name": "LodgementDate",
        "value": "24/04/2019 00:00:00 NZST"
    }

However when I add an additional-data to it i get the below

  <additional-data-set>
    <additional-data>
      <name>LodgementDate</name>
      <value>24/04/2019 00:00:00 NZST</value>
    </additional-data>
    <additional-data>
      <name>LodgementDate1</name>
      <value>25/05/2019 00:00:00 NZST</value>
    </additional-data> 
  </additional-data-set>

Converted to JSON

"additional-data": [
        {
            "name": "LodgementDate",
            "value": "24/04/2019 00:00:00 NZST"
        },
        {
            "name": "LodgementDate1",
            "value": "25/05/2019 00:00:00 NZST"
        }
    ],

As you can see it goes from being an object to an array when there is two or more additional-data.

I am currently trying the below code to validate it as an array or not

{
{% assign ads = body["p$ReadECODetailsResponse"].additional-data-set %}

"additional-data-set": {
            "additional-data": [

            {% if ads.additional-data.size < 0 %}
           {% for addDataBody in ads.additional-data %}
            {   
                "name": "{{addDataBody.name}}",
                "value": "{{addDataBody.value}}"
            }{% if forloop.last != true %},{% endif %}
            {% endfor %}
            {% break %}

            {% else %}
            {
                "name": "{{ads.additional-data.name}}",
                "value": "{{ads.additional-data.value}}"
            }
            {% break %}
            {% endif %}
            ]
        }
}

My problem is, the template cannot distinguish between the object and the array. And when calling each type (1 additional-data or 2 additional-data) the data will not call and be templated due to it not staying as an object/array.

Any ideas?

Lyderies
  • 43
  • 6

2 Answers2

1

Liquid template allows you to directly work on the XML objects. In this example you can directly iterate the input and read the values, without any overhead. Please find below liquid code, which always returns an array.

[
{% for item in content.additional-data-set %}
    {
        "name": "{{item.name}}",
        "value": "{{item.value}}"
    },
{% endfor %}]

The liquid template output snapshots: In a single : enter image description here For multiple objects: enter image description here

Pankaj More
  • 433
  • 3
  • 10
  • I have tried the code above however I am still getting an empty JSON with one object. When I have two objects it comes back in the array and your code works. – Lyderies Apr 11 '22 at 22:27
  • I am also doing this in the Azure API Manager, in the outbound policy if that makes a difference? – Lyderies Apr 11 '22 at 22:32
  • Yes, there is a slight difference in Azure APIM in terms of how the array elements are handled. As I can not add the code in comment section. I will post it as another answer – Pankaj More Apr 12 '22 at 05:32
1

If the liquid template is directly used in the Azure APIM, it has difference about how the array elements are handled. Using the JSONArrayfor tag should solve your problem. Please find below working code in the above example:

[
            {% JSONArrayFor item in body.additional-data-set %}
                {
                    "name": "{{item.name}}",
                    "value": "{{item.value}}"
                }
            {% endJSONArrayFor %}]
Pankaj More
  • 433
  • 3
  • 10