Varun05
Varun05

Reputation: 387

In Logic Apps JSON Array while parsing throwing error for single object but for multiple objects it is working fine

While parsing JSON in Azure Logic App in my array I can get single or multiple values/objects (Box as shown in below example)

Both type of inputs are correct but when only single object is coming then it is throwing an error "Invalid type. Expected Array but got Object "

Input 1 (Throwing error) : -

{ 

 "MyBoxCollection": 
             {
              "Box":{
              "BoxName": "Box 1"
              }
             }
}

Input 2 (Working Fine) : -

  { 

     "MyBoxCollection": 
                 [
                 {
                  "Box":{
                  "BoxName": "Box 1"
                  },
                  "Box":{
                  "BoxName": "Box 2"
                  }
                 }]
    }

JSON Schema :

"MyBoxCollection": {
          "type": "object",
          "properties": {
            "box": {
              "type": "array",
                items": {
                "type": "object",
                "properties": {
                  "BoxName": {
                    "type": "string"
                  },
......
.....
..
}

Error Details :-

[
  {
    "message": "Invalid type. Expected Array but got Object .",
    "lineNumber": 0,
    "linePosition": 0,
    "path": "Order.MyBoxCollection.Box",
    "schemaId": "#/properties/Root/properties/MyBoxCollection/properties/Box",
    "errorType": "type",
    "childErrors": []
  }
]

Upvotes: 4

Views: 6735

Answers (3)

nicdaniau
nicdaniau

Reputation: 3394

I used to use the trick of injecting a couple of dummy rows in the resultset as suggested by the other posts, but I recently found a better way. Kudos to Thomas Prokov for providing the inspiration in his NETWORG blog post.

The JSON parse schema accepts multiple choices as type, so simply replace

"type": "array"

with

"type": ["array","object"]

and your parse step will happily parse either an array or a single value (or no value at all).

You may then need to identify which scenario you're in: 0, 1 or multiple records in the resultset? I'm pasting below how you can create a variable (ResultsetSize) which takes one of 3 values (rs_0, rs_1 or rs_n) for your switch:

"Initialize_ResultsetSize": {
    "inputs": {
        "variables": [
            {
                "name": "ResultsetSize",
                "type": "string",
                "value": "rs_n"
            }
        ]
    },
    "runAfter": {
        "<replace_with_name_of_previous_action>": [
            "Succeeded"
        ]
    },
    "type": "InitializeVariable"
},
"Check_if_resultset_is_0_or_1_records": {
    "actions": {
        "Set_ResultsetSize_to_0": {
            "inputs": {
                "name": "ResultsetSize",
                "value": "rs_0"
            },
            "runAfter": {},
            "type": "SetVariable"
        }
    },
    "else": {
        "actions": {
            "Set_ResultsetSize_to_1": {
                "inputs": {
                    "name": "ResultsetSize",
                    "value": "rs_1"
                },
                "runAfter": {},
                "type": "SetVariable"
            }
        }
    },
    "expression": {
        "and": [
            {
                "equals": [
                    "@string(body('<replace_with_name_of_Parse_JSON_action>')?['<replace_with_name_of_root_element>']?['<replace_with_name_of_list_container_element>']?['<replace_with_name_of_item_element>']?['<replace_with_non_null_element_or_attribute>'])",
                    ""
                ]
            }
        ]
    },
    "runAfter": {
        "Initialize_ResultsetSize": [
            "Succeeded"
        ]
    },
    "type": "If"
},
"Process_resultset_depending_on_ResultsetSize": {
    "cases": {
        "Case_no_record": {
            "actions": {
            },
            "case": "rs_0"
        },
        "Case_one_record_only": {
            "actions": {
            },
            "case": "rs_1"
        }
    },
    "default": {
        "actions": {
        }
    },
    "expression": "@variables('ResultsetSize')",
    "runAfter": {
        "Check_if_resultset_is_0_or_1_records": [
            "Succeeded",
            "Failed",
            "Skipped",
            "TimedOut"
        ]
    },
    "type": "Switch"
}

Upvotes: 2

Ravi Teja
Ravi Teja

Reputation: 1

We faced a similar issue. The only solution we find is by manipulating the XML before conversion. We updated XML nodes which needs to be an array even when we have single element using this. We used a Azure function to update the required XML attributes and then returned the XML for conversion in Logic Apps. Hope this helps someone.

Upvotes: 0

Hury Shen
Hury Shen

Reputation: 15754

For this problem, I met another stack overflow post which is similar to this problem. While there is one "Box", it will be shown as {key/value pair} but not [array] when we convert it to json format. I think it is caused by design, so maybe we can just add a record "Box" at the source of your xml data such as:

<Box>specific_test</Box>

And do some operation to escape the "specific_test" in the next steps.

Another workaround for your reference:

If your json data has only one array, we can use it to do a judgment. We can judge the json data if it contains "[" character. If it contains "[", the return value is the index of the "[" character. If not contains, the return value is -1.

The expression shows as below:

indexOf('{"MyBoxCollection":{"Box":[aaa,bbb]}}', '[')

enter image description here

The screenshot above is the situation when it doesn't contain "[", it return -1.

Then we can add a "If" condition. If >0, do "Parse JSON" with one of the schema. If =-1, do "Parse JSON" with the other schema.

Hope it would be helpful to your problem~

Upvotes: 0

Related Questions