1

i am consuming wcf service which returns XML response, in Azure APIM i am transforming those into Json response by using the below APIM policy

<xml-to-json kind="direct" apply="always" consider-accept-header="false" />

It works fine until i get xml response as bleow like contains one title in the titles section,

<TitlesResponse>
    <Titles>
        <Title>
            <Name>BookTitle-1</Name>
            <Author>BookTitle-2</Author>
        </Title>
        <Title>
            <Name>BookTitle-1</Name>
            <Author>BookTitle-2</Author>
        </Title>
    </Titles>
    <Titles>
        <Title>
            <Name>BookTitle-1</Name>
        </Title>
    </Titles>
</TitlesResponse>

The json response for the above xml is as below

{
  "TitlesResponse": {
    "Titles": [
      {
        "Title": [
          {
            "Name": "BookTitle-1",
            "Author": "BookTitle-2"
          },
          {
            "Name": "BookTitle-1",
            "Author": "BookTitle-2"
          }
        ]
      },
      {
        "Title": {
          "Name": "BookTitle-1"
        }
      }
    ]
  }
}

The client expects always Json array in the Title section but it's returning jsonobject when only one title is there.

I tried this in outbound set-body but not working

  string xmlContent = context.Response.Body.As<string>(preserveContent: true);
  XmlDocument doc = new XmlDocument();
  doc.LoadXml(xmlContent);
  return JsonConvert.SerializeObject(doc);

Do we have any other way to convert to expected Json format from xml in the APIM

1 Answers1

0

I'm not sure if there's a real solution to this problem. It would be great if JsonConvert accepts also an XSD for serialization.

But I created a workaround:

The Request body is transformed from XML to JSON.

If the datatype is JOject, it will be replaced with an JArray:

<inbound>
    <base />
    <xml-to-json kind="direct" apply="always" consider-accept-header="false" />
    <set-body>@{
        var body = context.Request.Body.As<JObject>(true);

        JArray titles = body["TitlesResponse"]["Titles"] as JArray;
        for (int i = 0; i < titles.Count; i++)
        {
            JToken item = titles[i]["Title"];
            if(item.Type == JTokenType.Object && item.Type != JTokenType.Array )
            {
                JObject clone = (JObject)item.DeepClone();
                titles[i]["Title"] = new JArray();
                ((JArray)titles[i]["Title"]).Add(clone);
            }
        }
        return body.ToString();               
    }</set-body>
</inbound>

Response:

{
  "TitlesResponse": {
    "Titles": [
      {
        "Title": [
          {
            "Name": "BookTitle-1",
            "Author": "BookTitle-2"
          },
          {
            "Name": "BookTitle-1",
            "Author": "BookTitle-2"
          }
        ]
      },
      {
        "Title": [
          {
            "Name": "BookTitle-1"
          }
        ]
      }
    ]
  }
}
Markus Meyer
  • 3,327
  • 10
  • 22
  • 35
  • Thanks for your reply @markusmeyer , but this is not happening for one endpoint, i have several endpoints having the same issues. I'm just looking for some generic solution. – Ranjith Marutharaj Jul 19 '22 at 11:42