Многоуровневый динамический селектор Dataweave

#dataweave

Вопрос:

Я получаю как часть запроса сопоставления с набором полей, подобных этому:

 {
   "mapping": {
      "targetField1": "a.b.sourceField1",
      "targetField2": "a.c.sourceField2"
   }
}
 

Затем я вызываю службу, которая отвечает примерно так:

 {
   "a": {
      "b": {
         "sourceField1": "sourceValue1"
      },
      "c": {
         "sourceField2": "sourceValue2"
      }
   }
}
 

Наконец, мне нужно динамически сопоставить ответ, используя сопоставление, которое я получил в запросе, чтобы создать что-то подобное:

 {
   "targetField1": "sourceValue1",
   "targetField2": "sourceValue2"
}
 

Когда отображение находится на одном уровне, это довольно просто, потому что это просто использование ["sourceField1"] селектора, но я изо всех сил пытаюсь заставить работать многоуровневый (что-то вроде "a.b.sourceField1" ). Поддержка массивов, как "a.x[2].sourceFieldX" я полагаю, это другая история…

Ответ №1:

Это будет делать то, что вы хотите, и поддерживать массивы.

 %dw 2.0
output application/json

fun getField(payload: Any, field: String) = do {
    var path = field splitBy '.' reduce((pathPart, path=[]) ->
        if (pathPart contains '[') do {
            var pieces = pathPart splitBy '['
            ---
            pieces reduce((piece,subPath=path) -> 
                if (piece contains ']') subPath << (piece replace ']' with '') as Number
                else subPath << piece
            )
        }
        else path << pathPart
    )
    ---
    getField(payload, path)
}

fun getField(payload: Any, field: Array) =
    if (sizeOf(field) == 1) payload[field[0]]
    else getField(payload[field[0]], field[1 to -1])

var inData = { 
    "a" : {
        "b" : {
            "sourceField1": [{ "value": "sourceValue11" }]
        },
        "c" : {
            "sourceField2": "sourceValue2"
        }    
    }
}

var mappingData = { 
    "mapping": {
        "targetField1": "a.b.sourceField1[0].value",
        "targetField2": "a.c.sourceField2"
    } 
}

---
mappingData.mapping mapObject (($): getField(inData, $))
 

Выход:

 {
  "targetField1": "sourceValue11",
  "targetField2": "sourceValue2"
}