Error when using the StripLevels in the XMLToJSON in apigee X

This is the result without using StripLevels

{
    "Envelope": {
        "Header": null,
        "Body": {
            "getFormatosEmpresaResponse": {
                "formatos": [
                    {
                        "producto": {
                            "id": 1,
                            "desc": "Crédito y Seguro"
                        },
                        "plantilla": {
                            "id": 115197,
                            "desc": "ESTANDAR CCLA",
                            "tipoFormato": {
                                "desc": "PDF"
                            }
                        },
                        "artefacto": null,
                        "sucursal": {
                            "id": 1,
                            "nombre": "Sucursal 1"
                        },
                        "tipoFormato": "Estandar"
                    }
                ],
                "estado": {
                    "codigo": 0,
                    "descripcion": "Operacion Exitosa"
                }
            }
        }
    }
}

 This is the result using StripLevels

{
  "Header": null,
  "Body": {
    "getFormatosEmpresaResponse": {
      "formatos": [
        {
          "producto": {
            "id": 1,
            "desc": "Crédito y Seguro"
          },
          "plantilla": {
            "id": 115197,
            "desc": "ESTANDAR CCLA",
            "tipoFormato": {
              "desc": "PDF"
            }
          },
          "artefacto": null,
          "sucursal": {
            "id": 1,
            "nombre": "Sucursal 1"
          },
          "tipoFormato": "Estandar"
        }
      ],
      "estado": {
        "codigo": 0,
        "descripcion": "Operacion Exitosa"
      }
    }
  }
}

 This is the expected result

{
  "formatos": [
    {
      "producto": {
        "id": 1,
        "desc": "Crédito y Seguro"
      },
      "plantilla": {
        "id": 115197,
        "desc": "ESTANDAR CCLA",
        "tipoFormato": {
          "desc": "PDF"
        }
      },
      "artefacto": null,
      "sucursal": {
        "id": 1,
        "nombre": "Sucursal 1"
      },
      "tipoFormato": "Estandar"
    }
  ],
  "estado": {
    "codigo": 0,
    "descripcion": "Operacion Exitosa"
  }
}

This is the XMLToJson

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<XMLToJSON continueOnError="false" enabled="true" name="x2j-formatos-empresa">
  <DisplayName>X2J Formatos Empresa</DisplayName>
  <Properties/>
  <OutputVariable>response</OutputVariable>
  <Source>response</Source>
  <Options>
    <RecognizeNumber>true</RecognizeNumber>
    <RecognizeBoolean>true</RecognizeBoolean>
    <RecognizeNull>true</RecognizeNull>
    <TextAlwaysAsProperty>false</TextAlwaysAsProperty>
    <StripLevels>3</StripLevels>
    <TreatAsArray>
      <Path unwrap="true">Envelope/Body/getFormatosEmpresaResponse/formatos/formato</Path>
    </TreatAsArray>
  </Options>
</XMLToJSON>

 

Solved Solved
2 1 77
1 ACCEPTED SOLUTION

What you are describing is expected behavior. Per the documentation, you can strip levels away up to the first element that contains multiple children.

screenshot-20221110-100628.png

With multiple children it is impossible to know which element should be discarded, and which one retained.

If you want only that inner json, you can use a JS policy AFTER your XMLToJSON, with something like this:

 

<Javascript name='JS-prune-response' timeLimit='200' >
  <Source><![CDATA[
    var c = JSON.parse(context.getVariable('response.content'));
    context.setVariable('response.content', 
            JSON.stringify(c.Body.getFormatosEmpresaResponse));
  ]]>
  </Source>
</Javascript>

 

Or, as an alternative to JavaScript, you can use AssignMessage with the jsonpath function. Again this must be placed AFTER your XMLToJSON:

 

<AssignMessage name='AM-prune-response'>
  <AssignVariable>
    <Name>json_path_1</Name>
    <Value>$.Body.getFormatosEmpresaResponse</Value>
  </AssignVariable>
  <AssignVariable>
    <Name>response.content</Name>
    <Template>{jsonPath(json_path_1,response.content)}</Template>
  </AssignVariable>
</AssignMessage>

 

If you use either of these options then you probably don't need StripLevels in XMLToJSON. If you omit that option from the XMLToJSON policy, you would need to change $.Body to $.Envelope.Body in the AssignMessage, and change c.Body to c.Envelope.Body in the JavaScript.

View solution in original post

1 REPLY 1

What you are describing is expected behavior. Per the documentation, you can strip levels away up to the first element that contains multiple children.

screenshot-20221110-100628.png

With multiple children it is impossible to know which element should be discarded, and which one retained.

If you want only that inner json, you can use a JS policy AFTER your XMLToJSON, with something like this:

 

<Javascript name='JS-prune-response' timeLimit='200' >
  <Source><![CDATA[
    var c = JSON.parse(context.getVariable('response.content'));
    context.setVariable('response.content', 
            JSON.stringify(c.Body.getFormatosEmpresaResponse));
  ]]>
  </Source>
</Javascript>

 

Or, as an alternative to JavaScript, you can use AssignMessage with the jsonpath function. Again this must be placed AFTER your XMLToJSON:

 

<AssignMessage name='AM-prune-response'>
  <AssignVariable>
    <Name>json_path_1</Name>
    <Value>$.Body.getFormatosEmpresaResponse</Value>
  </AssignVariable>
  <AssignVariable>
    <Name>response.content</Name>
    <Template>{jsonPath(json_path_1,response.content)}</Template>
  </AssignVariable>
</AssignMessage>

 

If you use either of these options then you probably don't need StripLevels in XMLToJSON. If you omit that option from the XMLToJSON policy, you would need to change $.Body to $.Envelope.Body in the AssignMessage, and change c.Body to c.Envelope.Body in the JavaScript.