XMLtoJSON 政策

您正在查看的是 Apigee Edge 文档。
转到 Apigee X 文档
信息

内容

此政策用于将消息从可扩展标记语言 (XML) 格式转换为 JavaScript 对象表示法 (JSON),并为您提供若干选项来控制消息的转换方式。

假设意图将 XML 格式的响应转换为 JSON 格式的响应,则政策将附加到响应流(例如,Response / ProxyEndpoint/PostFlow)。

简介

在典型的中介情景中,入站请求流中的 JSON 到 XML 政策通常与出站响应流上的 XML 到 JSON 政策配对。通过以这种方式组合政策,您可以为本地仅支持 XML 的后端服务公开 JSON API。

如果 API 由不同的客户端应用使用,该客户端应用可能需要 JSON 或 XML 格式,则可以通过将 JSON 配置为 XML 以及将 XML 配置为 JSON 的政策来动态设置响应格式,以便有条件地执行。如需了解此使用场景的实现情况,请参阅流变量和条件


示例

有关在 JSON 和 XML 之间进行转换的详细讨论,请参阅 http://community.apigee.com/articles/1839/converting-between-xml-and-json-what-you-need-to-k.html

转换响应

<XMLToJSON name="ConvertToJSON">
  <Options>
  </Options>
  <OutputVariable>response</OutputVariable>
  <Source>response</Source>
</XMLToJSON>

此配置(将 XML 转换为 JSON 所需的最少配置)将 XML 格式的响应消息作为源,然后创建在 response OutputVariable 中填充的 JSON 格式消息。Edge 会自动将此变量的内容用作下一步处理步骤的消息。


元素参考

下面是您可以在此政策中配置的元素和属性。

<XMLToJSON async="false" continueOnError="false" enabled="true" name="XML-to-JSON-1">
    <DisplayName>XML to JSON 1</DisplayName>
    <Source>response</Source>
    <OutputVariable>response</OutputVariable>
    <Options>
        <RecognizeNumber>true</RecognizeNumber>
        <RecognizeBoolean>true</RecognizeBoolean>
        <RecognizeNull>true</RecognizeNull>
        <NullValue>NULL</NullValue>
        <NamespaceBlockName>#namespaces</NamespaceBlockName>
        <DefaultNamespaceNodeName>&</DefaultNamespaceNodeName>
        <NamespaceSeparator>***</NamespaceSeparator>
        <TextAlwaysAsProperty>true</TextAlwaysAsProperty>
        <TextNodeName>TEXT</TextNodeName>
        <AttributeBlockName>FOO_BLOCK</AttributeBlockName>
        <AttributePrefix>BAR_</AttributePrefix>
        <OutputPrefix>PREFIX_</OutputPrefix>
        <OutputSuffix>_SUFFIX</OutputSuffix>
        <StripLevels>2</StripLevels>
        <TreatAsArray>
            <Path unwrap="true">teachers/teacher/studentnames/name</Path>
        </TreatAsArray>
    </Options>
    <!-- Use Options or Format, not both -->
    <Format>yahoo</Format>
</XMLToJSON>

<XMLtoJSON> 属性

<XMLtoJSON async="false" continueOnError="false" enabled="true" name="XML-to-JSON-1"> 

下表介绍了所有政策父元素通用的特性:

属性 说明 默认 状态
name

政策的内部名称。name 属性的值可以包含字母、数字、空格、连字符、下划线和英文句点。此值不能超过 255 个字符。

(可选)使用 <DisplayName> 元素在管理界面代理编辑器中给政策添加不同的自然语言名称标签。

不适用 必需
continueOnError

设置为 false 可在政策失败时返回错误。这是大多数政策的预期行为。

设置为 true,即使在政策失败后,仍可以继续执行流。

false 可选
enabled

设置为 true 可强制执行政策。

设为 false关闭政策。即使政策仍附加到某个流,也不会强制执行该政策。

true 可选
async

此特性已弃用。

false 已弃用

<DisplayName> 元素

除了用于 name 属性之外,还可以用于在管理界面代理编辑器中给政策添加不同的自然语言名称标签。

<DisplayName>Policy Display Name</DisplayName>
默认

不适用

如果省略此元素,则会使用政策的 name 属性的值。

状态 可选
类型 字符串

<Source> 元素

包含要转换为 JSON 的 XML 消息的变量、请求或响应。

源消息的 HTTP Content-type 标头必须设置为 application/xml,否则政策不会强制执行。

如果未定义 <Source>,则系统会将其视为消息(当政策附加到请求流时解析为请求,或者在政策附加到响应流时响应)。

如果源变量无法解析或解析为非消息类型,则政策会提示错误。

<Source>response</Source>
默认 请求或响应,由将政策添加到 API 代理流的位置决定。
状态 可选
Type 消息

<OutputVariable> 元素

存储 XML 到 JSON 格式转换的输出。这通常与源值相同,即 XML 响应通常会转换为 JSON 响应。

XML 消息的载荷会被解析并转换为 JSON,XML 格式的消息的 HTTP Content-type 标头被设置为 application/json

如果未指定 OutputVariable,则 source 将被视为 OutputVariable。例如,如果 sourceresponse,则 OutputVariable 默认为 response

<OutputVariable>response</OutputVariable>
默认 请求或响应,由将政策添加到 API 代理流的位置决定。
状态 如果 <Source> 元素中定义的变量为字符串类型,则此元素是必填的。
Type 消息

<选项>

您可以使用选项来控制从 XML 到 JSON 的转换。您可以使用 <Options> 组(用于添加特定转化设置)或 <Format> 元素(用于引用预定义选项的模板)。您不能同时使用 <Options><Format>

如果未使用 <Format>,则需要使用 <Options>

<Options>/<RecognizeNumber> 元素

如果为 true,则 XML 载荷中的数字字段将保留其原始格式。

<RecognizeNumber>true</RecognizeNumber>

请参考以下 XML 示例:

<a>
  <b>100</b>
  <c>value</c>
</a>

如果为 true,则会转换为:

{
    "a": {
        "b": 100,
        "c": "value"
    }
}

如果为 false,则会转换为:

{
    "a": {
        "b": "100",
        "c": "value"
    }
}
默认 false
状态 可选
类型 布尔值

<Options>/<RecognizeBoolean> 元素

让转化保留布尔值 true/false 值,而不是将值转换为字符串。

<RecognizeBoolean>true</RecognizeBoolean>

对于以下 XML 示例:

<a>
  <b>true</b>
  <c>value</c>
</a>

如果为 true,则会转换为:

{
    "a": {
        "b": true,
        "c": "value"
    }
}

如果为 false,则会转换为:

{
    "a": {
        "b": "true",
        "c": "value"
    }
}
默认 false
状态 可选
类型 布尔值

<Options>/<RecognizeNull> 元素

允许您将空值转换为 null 值。

<RecognizeNull>true</RecognizeNull>

对于以下 XML:

<a>
  <b></b>
  <c>value</c>
</a>

如果为 true,则会转换为:

{
  "a": {
    "b": null,
    "c": "value"
  }
}

如果为 false,则会转换为:

{
  "a": {
    "b": {},
    "c": "value"
  }
}
默认 false
状态 可选
类型 布尔值

<Options>/<NullValue> 元素

表示源消息中已识别的 null 值应转换为的值。默认情况下,值为 null。只有当 RecognizeNull 为 true 时,此选项才有效。

<NullValue>not-present</NullValue>

默认 null
状态 可选
类型 字符串

<Options>/<NamespaceBlockName>
<Options>/<DefaultNamespaceNodeName>
<Options>/<NamespaceSeparator> 元素

一起使用这些元素。

<NamespaceBlockName>#namespaces</NamespaceBlockName>
<DefaultNamespaceNodeName>&</DefaultNamespaceNodeName>
<NamespaceSeparator>***</NamespaceSeparator>

请参考以下 XML 示例:

<a xmlns="http://ns.com" xmlns:ns1="http://ns1.com">
  <ns1:b>value</ns1:b>
</a>

如果未指定 NamespaceSeparator,则系统会生成以下 JSON 结构:

{
    "a": {
        "b": "value"
    }
}

如果元素 NamespaceBlockNameDefaultNamespaceNodeNameNamespaceSeparator 分别被指定为 #namespaces&***,则会生成以下 JSON 结构:

{
    "a": {
        "#namespaces": {
            "&": "http://ns.com",
            "ns1": "http://ns1.com"
        },
        "ns1***b": "value"
    }
}
默认 请参见上面的示例。
状态 可选
但是,如果您指定 <NamespaceBlockName>,则还必须指定另外两个元素。
Type 字符串

<Options>/<TextAlwaysAsProperty>
<Options>/<TextNodeName> 元素

一起使用这些元素。

如果设置为 true,则 XML 元素的内容将转换为字符串属性。

<TextAlwaysAsProperty>true</TextAlwaysAsProperty>
<TextNodeName>TEXT</TextNodeName>

对于以下 XML:

<a>
  <b>value1</b>
  <c>value2<d>value3</d>value4</c>
</a>

如果 TextAlwaysAsProperty 设置为 trueTextNodeName 指定为 TEXT,则会生成以下 JSON 结构:

{
  "a": {
    "b": {
      "TEXT": "value1"
    },
    "c": {
      "TEXT": [
        "value2",
        "value4"
        ],
        "d": {
          "TEXT": "value3"
        }
      }
    }
}

如果 TextAlwaysAsProperty 设置为 falseTextNodeName 指定为 TEXT,则会生成以下 JSON 结构:

{
  "a": {
    "b": "value1",
    "c": {
      "TEXT": [
        "value2",
        "value4"
      ],
      {
        "d": "value3",
      }
    }
}
默认 <TextAlwaysAsProperty>:false
<TextNodeName>:不适用
状态 可选
Type <TextAlwaysAsProperty>:布尔值
<TextNodeName>:字符串

<Options>/<AttributeBlockName>
<Options>/<AttributePrefix> 元素

一起使用这些元素。

允许您将值组合到 JSON 块中,并向属性名称附加前缀。

<AttributeBlockName>FOO_BLOCK</AttributeBlockName>
<AttributePrefix>BAR_</AttributePrefix>

请参考以下 XML 示例:

<a attrib1="value1" attrib2="value2"/>

如果这两个属性(AttributeBlockNameAttributePrefix)都按照 XML 到 JSON 示例中的定义指定,则会生成以下 JSON 结构:

{
  "a": {
    "FOO_BLOCK": {
      "BAR_attrib1": "value1",
      "BAR_attrib2": "value2"
    }
  }
}

如果仅指定 AttributeBlockName,则系统会生成以下 JSON 结构:

{
    "a": {
        "FOO_BLOCK": {
            "attrib1": "value1",
            "attrib2": "value2"
        }
    }
}

如果仅指定 AttributePrefix,则系统会生成以下 JSON 结构:

{
    "a": {
        "BAR_attrib1": "value1",
        "BAR_attrib2": "value2"
    }
}

如果均未指定,则系统会生成以下 JSON 结构:

{
    "a": {
        "attrib1": "value1",
        "attrib2": "value2"
    }
}
默认 请参见上面的示例。
状态 可选
类型 字符串

<Options>/<OutputPrefix>
<Options>/<OutputSuffix> 元素

一起使用这些元素。

<OutputPrefix>PREFIX_</OutputPrefix>
<OutputSuffix>_SUFFIX</OutputSuffix>

请参考以下 XML 示例:

<a>value</a>

如果这两个属性(OutputPrefixOutputSuffix)都按照 XML 到 JSON 示例中的定义指定,则会生成以下 JSON 结构:

PREFIX_{
    "a": "value"
}_SUFFIX

如果仅指定 OutputPrefix,则系统会生成以下 JSON 结构:

PREFIX_{
  "a" : "value"
}

如果仅指定 OutputSuffix,则系统会生成以下 JSON 结构:

{
  "a" : "value"
}_SUFFIX

如果 OutputPrefixOutputSuffix 均未指定,则系统会生成以下 JSON 结构:

{
    "a": "value"
}
默认 请参阅上文中的示例。
状态 可选
类型 字符串

<Options>/<StripLevels> 元素

<Options>
    <StripLevels>4</StripLevels>
</Options>

有时,XML 载荷(如 SOAP)包含很多您不希望在已转换的 JSON 中包含的父级别。下面是一个包含多个级别的示例 SOAP 响应:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/Schemata-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
      <GetCityWeatherByZIPResponse xmlns="http://ws.cdyne.com/WeatherWS/">
          <GetCityWeatherByZIPResult>
              <State>CO</State>
              <City>Denver</City>
              <Description>Sunny</Description>
              <Temperature>62</Temperature>
          </GetCityWeatherByZIPResult>
      </GetCityWeatherByZIPResponse>
  </soap:Body>
</soap:Envelope>

进入州、城市、描述和温度级别之前,共有 4 个级别。如果不使用 <StripLevels>,转换后的 JSON 响应将如下所示:

{
   "Envelope" : {
      "Body" : {
         "GetCityWeatherByZIPResponse" : {
            "GetCityWeatherByZIPResult" : {
               "State" : "CO",
               "City" : "Denver",
               "Description" : "Sunny",
               "Temperature" : "62"
            }
         }
      }
   }
}

如果要在 JSON 响应中删除这前 4 个级别,您需要设置 <StripLevels>4</StripLevels>,这将为您提供以下 JSON:

{
  "State" : "CO",
  "City" : "Denver",
  "Description" : "Sunny",
  "Temperature" : "62"
}

您可以删除级别,直到包含多个子元素的第一个元素为止。这是什么意思?我们来看一个更复杂的 JSON 示例:

{
   "Envelope" : {
      "Body" : {
         "GetCityForecastByZIPResponse" : {
            "GetCityForecastByZIPResult" : {
               "ResponseText" : "City Found",
               "ForecastResult" : {
                  "Forecast" : [
                     {
                        "ProbabilityOfPrecipiation" : {
                           "Nighttime" : "00",
                           "Daytime" : 10
                        }  ...

在此示例中,第 3 级是 GetCityForecastByZIPResponse,只有一个子级。因此,如果您使用的是 <StripLevels>3</StripLevels>(移除前三个级别),则 JSON 将如下所示:

{
   "GetCityForecastByZIPResult" : {
      "ResponseText" : "City Found",
      "ForecastResult" : {
         "Forecast" : [
            {
               "ProbabilityOfPrecipiation" : {
                  "Nighttime" : "00",
                  "Daytime" : 10
               }  ...

请注意,GetCityForecastByZIPResult 有多个子元素。由于其是包含多个子元素的第一个元素,因此您可以使用 <StripLevels>4</StripLevels> 删除最后一个级别,从而得到以下 JSON:

{
   "ResponseText" : "City Found",
   "ForecastResult" : {
      "Forecast" : [
         {
            "ProbabilityOfPrecipiation" : {
               "Nighttime" : "00",
               "Daytime" : 10
            }  ...

由于级别 4 是包含多个子元素的第一个级别,因此您不能删除低于该级别的任何级别。如果将删除级别设置为 5、6、7 等,您将会继续获得上述响应。

默认 0(无级别删除)
状态 可选
类型 整数

<Options>/<TreatAsArray>/<Path> 元素

<Options>
    <TreatAsArray>
        <Path unwrap="true">teachers/teacher/studentnames/name</Path>
    </TreatAsArray>
</Options>

此元素组合可确保 XML 文档中的值放在 JSON 数组中。例如,当子元素的数量发生变化(从一个到多个),并且您希望确保这些值始终位于数组中时,这样做非常有用。这样做有助于保持代码的稳定性,因为每次都可以用同样的方式从数组中获取数据。例如:无论数组中值的数量如何,$.teachers.teacher.studentnames[0] 都会获取数组中的第一个学生的姓名值。

让我们退后一步并看看 XML 到 JSON 的默认行为,然后探索如何使用 <TreatAsArray>/<Path> 控制输出。

当 XML 文档包含一个具有多个子元素值的元素(通常基于该元素的 maxOccurs='unbounded' 的架构)时,XML 到 JSON 的政策会自动将这些值放在数组中。例如,以下 XML 块

<teacher>
    <name>teacherA</name>
    <studentnames>
        <name>student1</name>
        <name>student2</name>
    </studentnames>
</teacher>

...自动转换为以下 JSON,但没有特殊的政策配置:

{
  "teachers" : {
      "teacher" : {
          "name" : "teacherA",
          "studentnames" : {
              "name" : [
                 "student1",
                 "student2"
              ]}
           }
      }
}

请注意,两个学生姓名放入一个数组中。

但是,如果 XML 文档中仅显示一个学生,则 XML 到 JSON 政策会自动将该值视为单个字符串,而不是字符串数组,如以下示例所示:

{
  "teachers" : {
      "teacher" : {
          "name" : "teacherA",
          "studentnames" : {
              "name" : "student1"
              }
          }
      }
}

在前面的例子中,类似数据采用的转换方式不同,一次以一个数组的形式转换,另一次以单个字符串形式转换。这就是 <TreatAsArray>/<Path> 元素允许您控制输出之处。例如,即使只有一个值,也可以确保学生姓名始终放在数组中。您可以通过识别要将其值放入数组中的元素的路径来对此进行配置,如下所示:

<Options>
    <TreatAsArray>
        <Path>teachers/teacher/studentnames/name</Path>
    </TreatAsArray>
</Options>

上述配置将写入 JSON,如下所示:

{
  "teachers" : {
      "teacher" : {
          "name" : "teacherA",
          "studentnames" : {
              "name" : ["student1"]
              }
            ]
          }
      }
}

请注意,student1 现在位于一个数组中。现在,无论是一个还是多个学生,您都可以使用以下 JSONPath 在您的代码中从 JSON 数组来检索学生:$.teachers.teacher.studentnames.name[0]

<Path> 元素还具有 unwrap 属性,下一部分会对此进行介绍。

默认 不适用
状态 可选
类型 字符串

属性

 <Options>
    <TreatAsArray>
        <Path unwrap="true">teachers/teacher/studentnames/name</Path>
    </TreatAsArray>
</Options>
特性 说明 状态 类型
取消封装

默认值:false

从 JSON 输出中移除该元素。使用它可简化或展平(“解封”) JSON,这也缩短了检索值所需的 JSONPath。例如,您可以展平 JSON 并使用 $.teachers.studentnames[*] 而不是 $.teachers.teacher.studentnames.name[*]

下面是一个 JSON 示例:

{
  "teachers" : {
      "teacher" : {
          "name" : "teacherA",
          "studentnames" : {
              "name" : [
                 "student1",
                 "student2"
              ]}...

在此示例中,您可以指出 teacher 元素和学生姓名 name 元素不是必需的。因此,您可以将它们移除或解封。您可以按如下方式配置 <Path> 元素来完成此操作:

<TreatAsArray>
    <Path unwrap="true">teachers/teacher</Path>
    <Path unwrap="true">teachers/teacher/studentnames/name</Path>
</TreatAsArray>

unwrap 属性设置为 true,并提供要解封的元素的路径。JSON 输出现在如下所示:

{
  "teachers" : [{
      "name" : "teacherA",
      "studentnames" : ["student1","student2"]
      }]...

请注意,由于 <Path> 元素位于 <TreatAsArray> 元素中,因此路径中的两个元素都将被视为 JSON 输出中的数组。

可选 布尔值

如需查看更多示例和功能演示,请参阅这篇 Apigee 社区文章:https://community.apigee.com/content/kbentry/33374/new-edge-minifeature-the-treatasarray-option-in-th.html

<格式>

格式让您能够控制从 XML 到 JSON 的转换。输入预定义模板的名称,该模板包含本主题中介绍的“选项”元素的特定组合。预定义格式包括:xml.comyahoogooglebadgerFish

使用 <Format> 元素或 <Options> 组。您不能同时使用 <Format><Options>

以下是每个预定义模板的“格式”定义。

xml.com

<RecognizeNull>true</RecognizeNull>
<TextNodeName>#text</TextNodeName>
<AttributePrefix>@</AttributePrefix>

yahoo

<RecognizeNumber>true</RecognizeNumber>
<TextNodeName>content</TextNodeName>

google

<TextNodeName>$t</TextNodeName>
<NamespaceSeparator>$</NamespaceSeparator>
<TextAlwaysAsProperty>true</TextAlwaysAsProperty>

badgerFish

<TextNodeName>$</TextNodeName>
<TextAlwaysAsProperty>true</TextAlwaysAsProperty>
<AttributePrefix>@</AttributePrefix>
<NamespaceSeparator>:</NamespaceSeparator>
<NamespaceBlockName>@xmlns</NamespaceBlockName>
<DefaultNamespaceNodeName>$</DefaultNamespaceNodeName>

元素语法:

<Format>yahoo</Format>
默认 输入可用格式的名称:
xml.comyahoogooglebadgerFish
状态 如果未使用 <Options>,则需要使用它。
类型 字符串

架构


错误参考信息

本部分介绍了在此政策触发错误时返回的错误代码和错误消息,以及 Edge 设置的故障变量。 在开发故障规则以处理故障时,请务必了解此信息。如需了解详情,请参阅您需要了解的有关政策错误的信息处理故障

运行时错误

政策执行时可能会发生这些错误。

故障代码 HTTP 状态 原因 修复
steps.xmltojson.ExecutionFailed 500 当输入负载 (XML) 为空或输入 XML 无效或格式有误时,就会出现此错误。
steps.xmltojson.InCompatibleType 500 如果 <Source> 元素中定义的变量类型与 <OutputVariable> 元素不同,则会出现此错误。<Source> 元素中包含的变量类型和 <OutputVariable> 元素必须与此变量完全匹配。
steps.xmltojson.InvalidSourceType 500 如果用于定义 <Source> 元素的变量类型无效,则会出现此错误。变量的有效类型为消息和字符串。
steps.xmltojson.OutputVariableIsNotAvailable 500 如果 XML 到 JSON 政策 的 <Source> 元素中指定的变量为字符串类型,并且未定义 <OutputVariable> 元素,则会出现此错误。如果 <Source> 元素中定义的变量为字符串类型,则 <OutputVariable> 元素是必填的。
steps.xmltojson.SourceUnavailable 500 如果 XML 到 JSON 政策的 <Source> 元素中的 message 变量是以下任一项,便会出现此错误:
  • 超出范围(在执行政策的特定流中不可用)
  • 无法解析(未定义)

部署错误

在您部署包含此政策的代理时,可能会发生这些错误。

错误名称 原因 修复
EitherOptionOrFormat 如果 XML 到 JSON 政策中未声明 <Options><Format> 中的一个元素,则 API 代理的部署将失败。
UnknownFormat 如果 XML 到 JSON 政策中的 <Format> 元素定义了未知格式,则 API 代理的部署将失败。预定义格式包括:xml.comyahoogooglebadgerFish

故障变量

发生运行时错误时,系统会设置这些变量。如需了解详情,请参阅您需要了解的有关政策错误的信息

变量 其中 示例
fault.name="fault_name" fault_name 是故障名称,如上面的运行时错误表中所列。故障名称是故障代码的最后一部分。 fault.name = "SourceUnavailable"
xmltojson.policy_name.failed policy_name 是抛出故障的政策的用户指定名称。 xmltojson.XMLtoJSON-1.failed = true

错误响应示例

{
  "fault": {
    "faultstring": "XMLToJSON[XMLtoJSON-1]: Source xyz is not available",
    "detail": {
      "errorcode": "steps.xml2json.SourceUnavailable"
    }
  }
}

故障规则示例

<faultrule name="VariableOfNonMsgType"></faultrule><FaultRule name="XML to JSON Faults">
    <Step>
        <Name>AM-SourceUnavailableMessage</Name>
        <Condition>(fault.name Matches "SourceUnavailable") </Condition>
    </Step>
    <Step>
        <Name>AM-BadXML</Name>
        <Condition>(fault.name = "ExecutionFailed")</Condition>
    </Step>
    <Condition>(xmltojson.XMLtoJSON-1.failed = true) </Condition>
</FaultRule>

相关主题

JSON 到 XML:JSON 到 XML 政策