【问题标题】:Dataweave 2 How to map Object to JSON Arrays of ObjectDataweave 2 如何将对象映射到对象的 JSON 数组
【发布时间】:2021-02-19 15:20:30
【问题描述】:

有一个 JSON 对象,我需要将其映射到对象数组,但经过多次尝试后无法立即获得结构。如果脚本变得非常复杂并且损害可读性和易于维护,那么将这个过程分成多个脚本而不是一个 dataweave 2 脚本会更好吗?

当前输出:

{
  "batchId": "71f7a8534907940cb1b5",
  "status": "1",
  "products": [
    {
      "materialNumber": "9780429435942",
      "errorMessages": [
        "Failure",
        "Mistake"
      ],
      "materialNumber": "9780429435950",
      "errorMessages": [
        "Exception"
      ]
    }
  ]
}

期望的输出:

{
  "batchId": "71f7a8534907940cb1b5",
  "status": "1",
  "products": [
    {
      "materialNumber": "9780429435942",
      "errorMessages": [
        "Failure",
        "Mistake"
      ]
    },
    {
      "materialNumber": "9780429435950",
      "errorMessages": [
        "Exception"
      ]
    }
  ]
}

DW2 脚本:

%dw 2.0
output application/json
var failedProducts = vars.response.materials filterObject ((product) -> product.status == "1")
---
{
    batchId: vars.batchId,
    status: vars.overallStatus,
    products: [
        failedProducts mapObject (value,key,index) -> {
            materialNumber: value.materialNumber,
            errorMessages: value.messages.*item.*msgText
        }
    ]
}

来源数据:

<response>
    <overallStatus>1</overallStatus>
    <materials>
      <item>
        <status>0</status>
        <materialNumber>9781231231231</materialNumber>
        <messages>
          <item>
            <msgText>Success</msgText>
          </item>
        </messages>
      </item>
      <item>
        <status>1</status>
        <materialNumber>9780429435942</materialNumber>
        <messages>
          <item>
            <msgText>Failure</msgText>
          </item>
          <item>
            <msgText>Mistake</msgText>
          </item>
        </messages>
      </item>
      <item>
        <status>1</status>
        <materialNumber>9780429435950</materialNumber>
        <messages>
          <item>
            <msgText>Exception</msgText>
          </item>
        </messages>
      </item>
    </materials>
</response>

【问题讨论】:

  • 我缺少一些值来自己尝试(例如变量),但如果您将errorMessages: value.messages.*item.*msgText 更改为[errorMessages: value.messages.*item.*msgText[0]],您也许可以获得所需的结果。

标签: mule dataweave


【解决方案1】:

您面临的问题是因为 XML 不本机支持数组。因此,在使用 dataweave 读取 XML 时,您需要明确提及您希望将某个路径作为数组读取,这正是您在 dataweave 中编写 value.messages.*item.*msgText 时所做的。你只需要对“item”元素(你称之为产品)做同样的事情。

这是您正在寻找的数据编织:

%dw 2.0
output application/json
var failedProducts = vars.response.materials.*item filter ((product) -> product.status == "1")
---
{
    batchId: vars.batchId,
    status: vars.overallStatus,
    products: failedProducts map (value) -> {
            materialNumber: value.materialNumber,
            errorMessages: value.messages.*item.*msgText
        }
 }

【讨论】:

  • 太好了,谢谢!正是我需要的。正如你所说,我的主要问题是过滤器不正确 - 缺少 .*item
  • 我认为你不需要.*msgText。它可能只是 .msgText 因为*item 已经处理好了。
  • @Thinker-101 是的,它不是必需的,但是为了将来更好的可读性,最好把它放上去。只要看一下就可以清楚地知道它是一个数组。但是,这仍然取决于您的偏好。
【解决方案2】:

以下代码(与您的不同)可为您提供所需的结果:

%dw 2.0
output application/json
var xml = '
<response>
    <overallStatus>1</overallStatus>
    <materials>
      <item>
        <status>0</status>
        <materialNumber>9781231231231</materialNumber>
        <messages>
          <item>
            <msgText>Success</msgText>
          </item>
        </messages>
      </item>
      <item>
        <status>1</status>
        <materialNumber>9780429435942</materialNumber>
        <messages>
          <item>
            <msgText>Failure</msgText>
          </item>
          <item>
            <msgText>Mistake</msgText>
          </item>
        </messages>
      </item>
      <item>
        <status>1</status>
        <materialNumber>9780429435950</materialNumber>
        <messages>
          <item>
            <msgText>Exception</msgText>
          </item>
        </messages>
      </item>
    </materials>
</response>
'
var data = read(xml,"application/xml")
var batchId = "71f7a8534907940cb1b5"
---
{
    batchId: batchId,
    status: data.response.overallStatus,
    products: 
        data.response.materials.*item filter ($.status as Number != 0)
        map {
            materialNumber: $.materialNumber,
            errorMessages: [$.messages.item]
        }
}

我确实使用了 DW 变量而不是您拥有的 vars

【讨论】:

    【解决方案3】:
    %dw 2.0
    output application/json
    var failedProducts = vars.response.materials filterObject ((value) -> value.status contains  "1")
    ---
    {
        batchId: vars.batchId,
        status: vars.overallStatus,
        products: failedProducts.*item map (value) -> {
                materialNumber: value.materialNumber,
                errorMessages: value.messages.*item.msgText
            }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-24
      • 1970-01-01
      • 2016-11-07
      • 2019-04-28
      • 2019-05-27
      相关资源
      最近更新 更多