XML到JSON转换问题

时间:2014-02-25 08:31:02

标签: json apigee

是否有一种方法可以参考模式将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设置为&#39; true&#39;然后结果json是:

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

如果将RecognizeNumber设置为&#39; false&#39;然后产生的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可以提供一些帮助

2 个答案:

答案 0 :(得分:2)

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

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

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

  1. 我将字符串~STR~添加到我的字符串值中,这些值可能看起来像布尔值或数字(强制数字和布尔值不被识别)。
  2. 我还为每个应该是数组元素的元素添加<element>~ARRAY~</element>两次(用实际元素名称替换“element”)。这会强制每个数组至少存在两个元素,这意味着您将始终获得数组类型。 (我的XSL使用xsl:for-each收集真实的数组元素。)
  3. 我猜你希望JSON响应成为顶层的未命名对象数组。 XML没有这个概念(总有一个根元素)。为了解决这个问题,我在名为<NOROOT>的XML中创建了一个根元素。这应该适用于JSON顶层的未命名数组或对象。
  4. 使用RecognizeNumber运行XMLToJSON并将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);
    
  6. 您的示例将在以下位置更改(在调用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中进行自定义清理。

答案 1 :(得分: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>

modifyXMLResponse.js

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

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

策略编号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>

modifyJsonResponse.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>