【问题标题】:XML to JSON Conversion IssuesXML 到 JSON 的转换问题
【发布时间】:2014-03-27 08:11:36
【问题描述】:

有没有参考架构将 XML 转换为 JSON 的方法。

假设xsd的一部分如下:

  <xs:complexType name="RegionStateResultType">
    <xs:sequence>
      <xs:element name="RegionOrState"     type="xs:string"  minOccurs="0" maxOccurs="1"/>
      <xs:element name="RegionOrStateCode" type="xs:string"  minOccurs="0" maxOccurs="1"/>
      <xs:element name="PinCode" type="xs:integer"  minOccurs="0" maxOccurs="1"/>
    </xs:sequence>
  </xs:complexType>

xml 是:

<RegionOrStateInfo>
    <RegionOrState>Tochigi</RegionOrState>
    <RegionOrStateCode>09</RegionOrStateCode>
    <PinCode>12345</PinCode>
</RegionOrStateInfo>

在使用 XMLtoJSON 转换策略时,如果我们将 RecognizeNumber 设置为 'true' 则生成的 json 为:

{
    "RegionOrState": "Tochigi",
    "RegionOrStateCode": "09" ,
    "PinCode":12345
},
{
    "RegionOrState": "Tokushima",
    "RegionOrStateCode": 36 ,
    "PinCode":12345
}

如果 RecognizeNumber 设置为 'false' 则生成的 json 为:

{
    "RegionOrState": "Tochigi",
    "RegionOrStateCode": "09" ,
    "PinCode": "12345"
},
{
    "RegionOrState": "Tokushima",
    "RegionOrStateCode": "36" ,
    "PinCode": "12345"
}

需要的json是:

{
    "RegionOrState": "Tochigi",
    "RegionOrStateCode": "09" ,
    "PinCode": 12345
},
{
    "RegionOrState": "Tokushima",
    "RegionOrStateCode": "36" ,
    "PinCode": 12345
}

有什么方法可以实现吗?

有没有人使用过 JSONSchema,有没有办法让转换器引用一个模式然后进行翻译?

在 XML 到 JSON 的转换中,我还遇到了单元素数组的一些问题。认为 JSONSchema 可以提供一些帮助

【问题讨论】:

    标签: json apigee


    【解决方案1】:

    您的问题的答案是,目前在 XMLToJSON 转换期间无法使用 xsd 文件或 JSON 架构。

    您可以通过编写了解有效负载的自定义代码(调整类型)来解决这些问题,但这需要一堆我不喜欢编写的自定义代码。

    我使用 XSL 和 JavaScript 策略解决了这些问题(强制数字/布尔型字段为字符串并强制将数组转换为数组,即使它们有 0 或 1 个元素)。

    1. 我将字符串 ~STR~ 添加到可能看起来像布尔值或数字的字符串值(强制数字和布尔值不被识别为此类)。
    2. 我还为每个应该是数组元素的元素添加了两次&lt;element&gt;~ARRAY~&lt;/element&gt;(将其中的“元素”替换为实际元素名称)。这会强制每个数组至少存在两个元素,这意味着您将始终获得一个数组类型。 (我的 XSL 使用 xsl:for-each 收集真正的数组元素。)
    3. 我猜您希望 JSON 响应是顶层的未命名对象数组。 XML 没有这个概念(总有一个根元素)。为了解决这个问题,我在我的 XML 中创建了一个名为 &lt;NOROOT&gt; 的根元素。这应该适用于 JSON 顶层的未命名数组或对象。
    4. 运行 XMLToJSON,并将 RecognizeNumber 和 RecognizeBoolean 设置为 true。 XML 将被转换为具有正确数据类型的 JSON。
    5. 运行 JavaScript 策略以去除您添加到 XML 中的提示以获得正确的转换。您可以对您所做的所有 XML 到 JSON 的转换使用相同的 JavaScript 策略。这是我的代码:

      var jsonResponse = context.getVariable("jsonResponse")
                                .replace(/"~STR~"/, "null")
                                .replace(/~STR~/g, "")
                                .replace(/"~ARRAY~",/g, "")
                                .replace(/"~ARRAY~"/g, "");
      var jsonVar = JSON.parse(jsonResponse);
      var jsonOut = jsonVar.ROOT;
      if (jsonOut.NOROOT !== undefined) {
          jsonOut = jsonOut.NOROOT;
      }
      
      response.content = JSON.stringify(jsonOut);
      

    您的示例将从以下位置更改(在调用 XMLToJSON 之前):

    <RegionOrStateInfo>
        <RegionOrState>Tochigi</RegionOrState>
        <RegionOrStateCode>09</RegionOrStateCode>
        <PinCode>12345</PinCode>
    </RegionOrStateInfo>
    <RegionOrStateInfo>
        <RegionOrState>Tokushima</RegionOrState>
        <RegionOrStateCode>36</RegionOrStateCode>
        <PinCode>12345</PinCode>
    </RegionOrStateInfo>
    

    到:

    <NOROOT>
        <RegionOrStateInfo>~ARRAY~</RegionOrStateInfo>
        <RegionOrStateInfo>~ARRAY~</RegionOrStateInfo>
        <RegionOrStateInfo>
            <RegionOrState>Tochigi</RegionOrState>
            <RegionOrStateCode>~STR~09</RegionOrStateCode>
            <PinCode>12345</PinCode>
        </RegionOrStateInfo>
        <RegionOrStateInfo>
            <RegionOrState>Tokushima</RegionOrState>
            <RegionOrStateCode>~STR~36</RegionOrStateCode>
            <PinCode>12345</PinCode>
        </RegionOrStateInfo>
    </NOROOT>
    

    在转换和运行 JavaScript 清理功能之后,生成的 JSON 将是(如下所示):

    [
        {
            "RegionOrState": "Tochigi",
            "RegionOrStateCode": "09",
            "PinCode": 12345
        },
        {
            "RegionOrState": "Tokushima",
            "RegionOrStateCode": "36",
            "PinCode": 12345
        }
    ]
    

    请注意,具有零条目的数组将生成[ ],而具有一个条目的数组将生成[ {entry} ]

    这个过程看起来很奇怪,但它可以工作,并且转换后不需要在 JavaScript 中进行自定义清理。

    【讨论】:

    • 谢谢 Mike。但这不是针对我用作示例的一个字段,而是针对几乎所有操作(大约数百个字段)。您认为我们是否应该进行替换,或者全部发送json 中的字符串并将其视为无类型,因为它将非常难以维护。如果几乎所有事情都需要这样做,最好在客户端应用程序中处理?
    • @rpattnaik 除非您将所有数据类型定义为 API 响应的一部分,否则客户端应用程序检查值的类型而不是假设可能是有意义的。这样,应用程序可以检查它是否是整数、字符串、数组等,然后在提取/解析数据时执行所需的操作而不会遇到问题。不过,这可能不是所有场景的最佳选择。
    • 我在需要使用 XSL 来更改格式的地方使用了它,它表现良好,即使是在包含数百个元素的大负载上也是如此。最好的部分是不需要自定义编程 - 找到字符串字段并将 ~STR~ 添加到 XSL,你就完成了。对于您在上面显示的简单有效负载,我可能不会使用 XSL——编写几行 JavaScript 来完成您想要的操作会很容易。作为一名应用程序开发人员,我可以看到使用 Michael 的防御性编程。不过,作为 API 开发人员,如果可以避免的话,我绝不会在 JSON 响应中发送错误的数据类型。
    【解决方案2】:

    当数组只包含一个对象时,我遇到了同样的 apigee 数组处理问题。 Apigee 不维护 xsd,因此当数组包含单个对象时,apigee 很难理解它。我添加了两个 javascript 策略来解决这个问题。

    政策编号 1:此政策在 apigee 将 xml 转换为 json 之前的流程中应用。

    目的:在每个数组中添加银行对象。

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Javascript async="false" continueOnError="false" enabled="true" timeLimit="200" name="Modify-XML-response">
        <DisplayName>Modify XML response</DisplayName>
        <FaultRules/>
        <Properties/>
        <ResourceURL>jsc://modifyXMLResponse.js</ResourceURL>
    </Javascript>
    

    修改XMLResponse.js

    我在这里添加一个空白的 Sfiwfalertquerynotes 对象,其中数组至少有一个 Sfiwfalertquerynotes 对象。

    var jsonResponse = response.content;
    var returnStr = jsonResponse;
    returnStr = returnStr.split("</Sfiwfalertquerynotes>").join("</Sfiwfalertquerynotes><Sfiwfalertquerynotes/>");
    response.content = returnStr; 
    

    Policy Number 2:此策略在apigee将xml转换为json后的流程中应用。

    目的: 因为我们在apigee将xml转换为json时在xml数组中添加了一个空白对象,所以每个数组都会有像{}或“”这样的空白对象。我们需要从每个数组中清除所有这些。

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Javascript async="false" continueOnError="false" enabled="true" timeLimit="200" name="modifyjsonresponse">
        <DisplayName>Modify Json response</DisplayName>
        <FaultRules/>
        <Properties/>
        <ResourceURL>jsc://modifyJsonResponse.js</ResourceURL>
    </Javascript>
    

    修改JsonResponse.js

    var jsonResponse = response.content;
    var returnStr = jsonResponse;
    returnStr = returnStr.split("},\"\"").join("}")
    response.content = returnStr; 
    

    目标端点预流:

    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <Name>SetTargetURL</Name>
            </Step>
        </Request>
        <Response>
            <Step>
                <Name>Modify-XML-response</Name>
            </Step>
            <Step>
                <Name>XmltoJson</Name>
            </Step>
            <Step>
                <FaultRules/>
                <Condition>(content-type = "application/xml") or (content-type = "text/xml")</Condition>
                <Name>ResponseJsontoXml</Name>
            </Step>
            <Step>
                <Name>modifyjsonresponse</Name>
            </Step>
        </Response>
    </PreFlow>
    

    【讨论】:

      猜你喜欢
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      • 2014-12-18
      • 2013-03-09
      • 1970-01-01
      • 2014-11-24
      • 1970-01-01
      • 2022-01-22
      相关资源
      最近更新 更多