在SAP CPI中使用Groovy实现XML转JSON的格式调整问题
SAP CPI中Groovy XML转指定JSON格式的调整方案
问题场景
在SAP CPI中使用标准XML转JSON转换器无法得到预期格式,编写Groovy代码后,生成的JSON里Rows数组的元素是直接的数组,需要调整为每个元素是包含Value键的对象。
原Groovy代码
def xml = """<Rows> <Values> <Value> <Name>DummyTest_1</Name> <Site.Value>3</Site.Value> <Description>Dummy PN For Test 1</Description> <Type.Value>N</Type.Value> <BuyerCode.Value/>, <PlannerCode.Value/>, <PlannerCode.Description/>, <ABCCode.Value>Default</ABCCode.Value> <UnitOfMeasure.Value>LB</UnitOfMeasure.Value> <SafetyStockQty>1</SafetyStockQty> <StdUnitCost>10</StdUnitCost> <AverageSellingPrice>15</AverageSellingPrice> <ProductFamily.Value/> <ProductGroup1>CHC</ProductGroup1> <IncrementalRule.Value>Default</IncrementalRule.Value> <MUEPoolNettingType.Value>Ignore</MUEPoolNettingType.Value> <PlanningCalendars.Value>Default</PlanningCalendars.Value> <SourceRule.Value>Default</SourceRule.Value> </Value> <Value> <Name>DummyTest_2</Name> <Site.Value>4</Site.Value> <Description>Dummy PN For Test 2</Description> <Type.Value>H</Type.Value> <BuyerCode.Value/>, <PlannerCode.Value/>, <PlannerCode.Description/>, <ABCCode.Value>Default2</ABCCode.Value> <UnitOfMeasure.Value>BL</UnitOfMeasure.Value> <SafetyStockQty>2</SafetyStockQty> <StdUnitCost>20</StdUnitCost> <AverageSellingPrice>16</AverageSellingPrice> <ProductFamily.Value/> <ProductGroup1>CHC</ProductGroup1> <IncrementalRule.Value>Default</IncrementalRule.Value> <MUEPoolNettingType.Value>Ignore</MUEPoolNettingType.Value> <PlanningCalendars.Value>Default</PlanningCalendars.Value> <SourceRule.Value>Default</SourceRule.Value> </Value> </Values> </Rows>""" def parsed = new XmlSlurper().parseText(xml) def values = ['Rows' : parsed.'**'.findAll{it.name() == 'Value'}.collect{element -> element.children().breadthFirst()*.name().findAll { !element."$it".children().size() }.collect{element."$it".text()}}] def fields = ['Fields' : parsed.'**'.find{it.name() == 'Value'}.collect{element -> element.children().breadthFirst()*.name() .findAll { !element."$it".children().size() } .collect{element."$it".name()}}] fields += values println new groovy.json.JsonBuilder(fields).toPrettyString()
当前输出
{ "Fields": [ [ "Name", "Site.Value", "Description", "Type.Value", "BuyerCode.Value", "PlannerCode.Value", "PlannerCode.Description", "ABCCode.Value", "UnitOfMeasure.Value", "SafetyStockQty", "StdUnitCost", "AverageSellingPrice", "ProductFamily.Value", "ProductGroup1", "IncrementalRule.Value", "MUEPoolNettingType.Value", "PlanningCalendars.Value", "SourceRule.Value" ] ], "Rows": [ [ "DummyTest_1", "3", "Dummy PN For Test 1", "N", "", "", "", "Default", "LB", "1", "10", "15", "", "CHC", "Default", "Ignore", "Default", "Default" ], [ "DummyTest_2", "4", "Dummy PN For Test 2", "H", "", "", "", "Default2", "BL", "2", "20", "16", "", "CHC", "Default", "Ignore", "Default", "Default" ] ] }
预期输出
{ "Fields": [ [ "Name", "Site.Value", "Description", "Type.Value", "BuyerCode.Value", "PlannerCode.Value", "PlannerCode.Description", "ABCCode.Value", "UnitOfMeasure.Value", "SafetyStockQty", "StdUnitCost", "AverageSellingPrice", "ProductFamily.Value", "ProductGroup1", "IncrementalRule.Value", "MUEPoolNettingType.Value", "PlanningCalendars.Value", "SourceRule.Value" ] ], "Rows": [ { "Value":[ "DummyTest_1", "3", "Dummy PN For Test 1", "N", "", "", "", "Default", "LB", "1", "10", "15", "", "CHC", "Default", "Ignore", "Default", "Default" ] }, { "Value":[ "DummyTest_2", "4", "Dummy PN For Test 2", "H", "", "", "", "Default2", "BL", "2", "20", "16", "", "CHC", "Default", "Ignore", "Default", "Default" ] } ] }
修改方案
只需调整values变量的生成逻辑,将每个值数组包装成包含Value键的Map对象即可:
修改后的Groovy代码
def xml = """<Rows> <Values> <Value> <Name>DummyTest_1</Name> <Site.Value>3</Site.Value> <Description>Dummy PN For Test 1</Description> <Type.Value>N</Type.Value> <BuyerCode.Value/>, <PlannerCode.Value/>, <PlannerCode.Description/>, <ABCCode.Value>Default</ABCCode.Value> <UnitOfMeasure.Value>LB</UnitOfMeasure.Value> <SafetyStockQty>1</SafetyStockQty> <StdUnitCost>10</StdUnitCost> <AverageSellingPrice>15</AverageSellingPrice> <ProductFamily.Value/> <ProductGroup1>CHC</ProductGroup1> <IncrementalRule.Value>Default</IncrementalRule.Value> <MUEPoolNettingType.Value>Ignore</MUEPoolNettingType.Value> <PlanningCalendars.Value>Default</PlanningCalendars.Value> <SourceRule.Value>Default</SourceRule.Value> </Value> <Value> <Name>DummyTest_2</Name> <Site.Value>4</Site.Value> <Description>Dummy PN For Test 2</Description> <Type.Value>H</Type.Value> <BuyerCode.Value/>, <PlannerCode.Value/>, <PlannerCode.Description/>, <ABCCode.Value>Default2</ABCCode.Value> <UnitOfMeasure.Value>BL</UnitOfMeasure.Value> <SafetyStockQty>2</SafetyStockQty> <StdUnitCost>20</StdUnitCost> <AverageSellingPrice>16</AverageSellingPrice> <ProductFamily.Value/> <ProductGroup1>CHC</ProductGroup1> <IncrementalRule.Value>Default</IncrementalRule.Value> <MUEPoolNettingType.Value>Ignore</MUEPoolNettingType.Value> <PlanningCalendars.Value>Default</PlanningCalendars.Value> <SourceRule.Value>Default</SourceRule.Value> </Value> </Values> </Rows>""" def parsed = new XmlSlurper().parseText(xml) // 关键修改:将每个值数组包装成["Value": 数组]的Map def values = ['Rows' : parsed.'**'.findAll{it.name() == 'Value'}.collect{element -> def valueList = element.children().breadthFirst()*.name().findAll { !element."$it".children().size() }.collect{element."$it".text()} [Value: valueList] }] def fields = ['Fields' : parsed.'**'.find{it.name() == 'Value'}.collect{element -> element.children().breadthFirst()*.name() .findAll { !element."$it".children().size() } .collect{element."$it".name()}}] fields += values println new groovy.json.JsonBuilder(fields).toPrettyString()
说明
原代码中collect直接返回值数组,修改后在collect闭包里先生成值数组,再返回[Value: valueList]格式的Map,这样Rows数组的每个元素就变成了包含Value键的对象,完全匹配预期格式。
内容的提问来源于stack exchange,提问作者Kaushik
相关产品推荐
相关产品推荐

