如何在不使用 Dataweave 中的列名的情况下创建 Excel 文件键值映射?

问题描述

我正在将一个 excel 文件 (.xlsx) 读取到一个 json 数组中,并且我正在创建一个映射,因为我想分别对每一列应用验证。我可以像这样使用列名访问它, Excel文件是:

column A,column B
value of Column A,value of column B

我是这样访问的: 有效载荷映射(项目,索引)-> "列名 A" : item."列名 A",“列名 B”:项目。“列名 B”

其中 A 列和 B 列是 excel 列标题

我想要做的是创建相同的地图,但使用列索引

payload map(item,index) ->
        item[0].key : item[0],item[1].key : item[1]

这样我就不必对 excel 标题名称进行硬编码,而且我可以依赖 excel 列的索引。

我尝试使用 pluck $$ 创建键映射,但我无法创建键值映射,我无法使用 item[0] 作为映射中的键。

如何在不使用excel列标题名称的情况下实现上述目标?

预期的输出应该是这样的:

{ 
  "Column A " : "value of Column A","Column B" : "value of Column B","Errors" : "Column A is not valid"
}

解决方法

尝试仅使用索引。它应该可以正常工作。

%dw 2.0
output application/json
---
({ "someKey": "Val1","lksajdfkl": "Val2" })[1]

结果

"Val2"

如果你想使用一个变量作为键,你必须把它用括号括起来。

EG,要将 { "key": "SomeOtherKey","val": 123 } 转换为 { "SomeOtherKey": 123 },您可以执行 (payload.key): payload.val

,

假设您想验证从 Excel 文件加载的每个有效负载项,您可以使用以下 DataWeave 表达式:

%dw 2.0
output application/json
fun validate(col,val) = 
  if (isEmpty(val)) {"error": col ++ ": value is null or empty"}
  else {}
fun validateRow(row) = 
  "Errors": 
    flatten([] << ((row mapObject ((value,key,index) -> ((validate((key),value))))).error default []))
---
payload map (item,index) -> item ++ validateRow(item)

使用以下输入负载:

[
    {"col1": "val1.1","col2": "val1.2","col3": "val1.3"},{"col1": "val2.1","col2": "val2.2","col3": null}
]

会导致:

[
  {
    "col1": "val1.1","col3": "val1.3","Errors": [
      
    ]
  },{
    "col1": "val2.1","col3": null,"Errors": [
      "col3: value is null or empty"
    ]
  }
]

该表达式将导致输出与您期望的略有不同,但此版本将允许您拥有一系列错误消息,以便稍后在您的流程中更容易操作。

要记住的一件事是每列可能有多个错误消息。如果是这种情况,则 DataWeave 表达式需要进行一些调整。

,

试试这个:

%dw 2.0
output application/json

var rules = {
    "0": {
        key: "Column A",val: (val) -> !isEmpty(val),},"1": {
        key: "Column B",val: (val) -> val ~= "value of Column B"
    }
}

fun validate(v,k,i) = 
    [
        ("Invalid column name: '$(k)' should be '$(rules[i].key)'") if (rules[i]? and rules[i].key? and k != rules[i].key),("Invalid value for $(rules[i].key): '$(v default "null")'") if (rules[i]? and rules[i].val? and (!(rules[i].val(v))))
    ]

fun validate(obj) =
    obj pluck { v: $,k: $$ as String,i: $$$ as String } reduce ((kvp,acc={}) -> 
    do {
        var validation = validate(kvp.v,kvp.k,kvp.i)
        ---
        {
            (acc - "Errors"),(kvp.k): kvp.v,("Errors": (acc.Errors default []) ++
                (if (sizeOf(validation) > 0) validation else [])
            ) if(acc.Errors? or sizeOf(validation) > 0)
        }
    }
)

---
payload map validate($)

输出:

[
  {
    "Column A": "value of Column A","Column B": "value of Column B"
  },{
    "Column A": "","Column B": "value of Column B","Errors": [
      "Invalid value for Column A: ''"
    ]
  },{
    "Column A": "value of Column A","Column B": "value of Column C","Errors": [
      "Invalid value for Column B: 'value of Column C'"
    ]
  },{
    "Column A": null,"Column C": "value of Column D","Errors": [
      "Invalid value for Column A: 'null'","Invalid column name: 'Column C' should be 'Column B'","Invalid value for Column B: 'value of Column D'"
    ]
  }
]