当输入在第一条记录中没有全部 headers 时,如何使用 DataWeave 创建带有 headers 的 CSV 输出

How to use DataWeave to create a CSV output with headers when the input doesn't has all headers in the first record

我有json个没有固定长度的数组,例如

[
 {
  a: 1
 },
 {
  a: 1,
  b: 2
 },
 {
  a: 1,
  c: 3
 },
 {
  a: 1,
  b: 2,
  d: 4,
  f: 6
 }
]

我需要使用 header 将它们转换为 CSV 文件。下面的脚本只有 return header 的第一行,而不是所有列。可以知道怎么操作吗?

%dw 2.0
output application/csv separator = "    ", escape = "", header = true, encoding="UTF-8"
---
payload

我期待这样的结果

我对问题的理解是,您的输入没有包含输出 CSV 的所有 header 的第一行行。需要从每一行中收集 header。

我通过从每条记录中获取所有 header 来分别计算所有 header 解决了这个问题,然后在开始时手动创建一行 headers 元素, 并禁用自动 header 生成。我不对性能提出任何要求。这对于更大的有效负载可能是不利的,因为该脚本基本上对每条记录进行两次迭代。我将逻辑封装在函数中以便于重用。

主要的复杂性在于重新创建输出记录,为缺失的列添加空值并遵守函数 addMissingValue() 中的原始顺序。这是必需的,因为这种情况不在 DataWeave built-in 对 CSV 的支持范围内。

%dw 2.0
output application/csv header=false
var collectHeaders=payload 
    map namesOf($) reduce ((item, accumulator=[]) -> (accumulator ++ item) distinctBy ((item, index) -> item) )

fun createHeaderLine(x)=[collectHeaders map {($): $} 
    reduce ((item, accumulator={}) -> accumulator ++ item)]

fun addMissingValue(o)=
    collectHeaders 
        map ( if (o[$]== null) {($): null} else {($): o[$]} ) 
        reduce ((item, accumulator={}) -> accumulator ++ item) 
 
---
createHeaderLine(payload) ++ (payload map addMissingValue($))

输入(为清楚起见,格式正确 JSON,如果你的格式是 Java 或其他格式,它的工作方式相同):

[
    {
        "a": 1
    },
    {
        "a": 1,
        "b": 2
    },
    {
        "a": 1,
        "c": 3
    },
    {
        "a": 1,
        "b": 2,
        "d": 4,
        "f": 6
    }
]

输出:

a,b,c,d,f
1,,,,
1,2,,,
1,,3,,
1,2,,4,6

我注意到您的示例脚本使用了由多个空格组成的分隔符。我没有在我的解决方案中使用它,因为它不相关。如果需要,请随时添加。请注意,CSV 是一种带分隔符的文本格式,而不是固定长度格式。

另一个解决方案是使用我的 csv-module (https://github.com/rbutenuth/csv-module)。您在配置中指定 headers 并且不要从输入数据中获取它们。

即使您输入的数据在整个数据集中缺少一列,也能正常工作。并提供元数据以便更轻松地使用 DataWeave 进行映射。