APIM – handling a JSON array response from a send-request policy

Posted: April 29, 2020  |  Categories: Azure

In this blog I show an example of a APIM send-request policy , subsequently using the response, a JSON array, in another call to the backend service. I highlight a special problem I had retrieving a value from the JSON array and how I overcame it.

Incidentally the API aggregation solution is a tactical solution until a purpose built API can be created in MYSite.

The APIM Send -request policy

I show a simple version of the policy .

The rest this blog will talk about the line where we retrieve a JSON value for ItemCode namely

@((string)((IResponse)context.Variables[“code”]).Body.As<JObject>()[0][“ItemCode”])” />

The Issue

On running the policy I get an error like

"messages": [
    {
        "message": "Expression evaluation failed.",
        "expression": "(string)((IResponse)context.Variables[\"code\"]).Body.As<JObject>()[0][\"ItemCode\"]",
        "details": "The message body is not a valid JSON. Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.\r\n   at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings)\r\n   at Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody.AsJObject(Stream stream, Encoding encoding, JsonSerializerSettings settings)\r\n   at Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody.As[T](Boolean preserveContent)"
    },
    "Expression evaluation failed. The message body is not a valid JSON. Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.\r\n   at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings)\r\n   at Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody.AsJObject(Stream stream, Encoding encoding, JsonSerializerSettings settings)\r\n   at Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody.As[T](Boolean preserveContent)",
    "Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1."
] }

The JSON that is returned is a headless array shown below

[    {        “ItemCode”: 5573,        “ProductCode”: “5573”    }]

This is valid JSON but APIM does not like it because it expects non-blank path like

{“Codes”: [    {        “ItemCode”: 5573,        “ProductCode”: “5573”    }] }

A solution

I can’t change the APIM implemenation of JObject but I can workaround it. Firstly I cast the IResponse to a string instead of a JObject. Secondly I prepend the string with {“Codes”: and postpend with a }. Now the array has a head. Thirdly parse the string as a JObject. Finally retrieve the ItemCode value. thus the final solution contains this fragment.

<set-variable name="codes" value="@("{\"Codes\":" + (string((IResponse)context.Variables["code"]).Body.As<string>() + "}")" />

<set-variable name="itemcode" value="@{JObject codes = JObject.Parse((string)context.Variables["codes"]);
return (string)codes["Codes"][0]["ItemCode"];
}" />
<set-backend-service base-url="{{site-BaseUrl-AU}}" />

<base />

 <rewrite-uri template="@("/api/s_v1/Image/GetImage/" + ((string)context.Variables["itemcode"]) + "/")" />

Conclusion

While the JObject implementation in APIM does not support a “headless” JSON array it can be worked around using an APIM expression.

BizTalk360
BizTalk Server

Over 500+ customers across
30+ countries depend on BizTalk360

Learn More
Serverless360
Azure

Manage and monitor serverless
components effortlessly

Learn More
Atomicscope
Business Users

Monitor your Business Activity in iPaaS
or Hybrid integration solutions

Learn More

Back to Top