如何使用 DW v1.0 迭代带有对象的数组

问题描述

我已经有了这个对象的答案,但正在寻找一种方法来改进它以便能够处理相同对象类型的数组:

%dw 1.0
%output application/json

%function filterKeys(o,k)
    o mapObject
            { 
                ($$): 
                    $ when ($ is :string and not (k contains ($$ as :string)))
                    otherwise orderMembers($,k)
            } 
            orderBy $$

%function splitString(s) s splitBy "," map trim $

%function orderMembers(x,k)
    x match {
        a is :array -> a orderBy $,o is :object -> filterKeys(o,k),s is :string -> orderMembers(splitString(s),k)
             when s  contains ',' otherwise s,default -> $
    }
    
%var testData={ccc:"333",ddd: ["555","333","222"],bbb: "223,221,222",eee: "456,789,123",aaa: 11}
---
orderMembers(testData,["bbb"]) 

如何修改它以便它可以处理该数据样本:

%var testData=[{ccc:"333",aaa: 11},{ccc:"333",aaa: 11}]

解决方法

我将做出有根据的猜测,orderBy() 抛出错误 You cannot compare a value of type ::object.,因为它试图对对象数组进行排序,而不是对原本预期的数组类型的字符串进行排序。

一个简单但不完全证明的解决方案是在尝试排序之前检查数组的第一个元素是否是字符串。如果不是,我们可以假设它是对象并递归处理它们。这可以改进,检查对象,检查数组的所有元素的类型等。我将把它作为练习给读者。

简单的解决方法是改变:

     a is :array -> a orderBy $,

     a is :array -> (a orderBy $) 
           when (a[0] is :string) 
           otherwise (a map orderMembers($,k)),

您可以改进 when 条件,例如检查数组中的所有元素是否属于兼容类型。我觉得这在 Mule 4 中会更容易,因为 DataWeave 2.0 有很多有用的函数来实现对数组和对象的测试。