Jolt: объединить массивы из свойств

Я пытаюсь извлечь и объединить объекты из массива, содержащегося в некоторых (но не во всех) моих входных элементов. Использование библиотеки преобразований JOLT JSON.

Кроме того, массивы, которые я пытаюсь объединить, содержат объекты, которые не всегда имеют одинаковые свойства. Один ключ может присутствовать в некоторых, но не в других.

Примером является надуманное / бессмысленное упрощение, но оно имеет общую форму наших данных.

Входные данные:

{
  "Widgets": [
    {
      "Id": "1",
      "PetFriendly": "True",
      "Features": [
        {
          "Name": "Easy Button",
          "Type": "Button"
        },
        {
          "Name": "Lunch Lever",
          "Type": "Food Service",
          "MenuItems": [
            "Pizza",
            "Cheezburger"
          ]
        }
      ]
    },
    {
      "Id": "2",
      "PetFriendly": "True"
    },
    {
      "Id": "3",
      "PetFriendly": "False",
      "Features": [
        {
          "Name": "Missles",
          "Type": "Attack"
        }
      ]
    },
    {
      "Id": "4",
      "PetFriendly": "False",
      "Features": [
        {
          "Name": "Bombs",
          "Type": "Attack",
          "MenuItems": [
            "Rat Poison"
          ]
        }
      ]
    }
  ]
}

Желаемый результат:

  {
    "Widgets": [
      {
        "Id": "1"
        "PetFriendly": "True"
      },
      {
        "Id": "2"
        "PetFriendly": "True"
      },
      {
        "Id": "3",
        "PetFriendly": "False"
      },
      {
        "Id": "4",
        "PetFriendly": "False"
      }
    ],
    "Features": [
      {
        "WidgetId": "1",
        "Name": "Easy Button",
        "Type": "Button"
      },
      {
        "WidgetId": "1",
        "Name": "Lunch Lever",
        "Type": "Food Service",
        "MenuItems": [
            "Pizza",
             "Cheezburger"
         ]
      },
      {
        "WidgetId": "3",
        "Name": "Missles",
        "Type": "Attack"
      },
      {
        "WidgetId": "4",
        "Name": "Bombs",
        "Type": "Attack",
        "MenuItems": [
          "Rat Poison"
        ]
      }
    ]
  }

Я попробовал много преобразований безуспешно, и прочитал всю документацию ShiftR и его модульные тесты. Небольшая помощь?

2 ответа

Решение

Спекуляция

[
  {
    "operation": "shift",
    "spec": {
      "Widgets": {
        "*": {
          // build the finished "Widgets" output
          "Id": "Widgets[&1].Id",
          "PetFriendly": "Widgets[&1].PetFriendly",
          // 
          // Process the Features, by pushing the Id
          //  down into them, but maintain the same doubly
          //  nested structure.
          // Shift works property by property, so first 
          //  fix the properties in side each Features element,
          //  (pulling ID down).
          // Then in a 2nd Shift can accumulate things into array. 
          "Features": {
            "*": {
              "@(2,Id)": "temp[&3].Features[&1].WidgetId",
              "*": "temp[&3].Features[&1].&"
            }
          }
        }
      }
    }
  },
  {
    "operation": "shift",
    "spec": {
      // passthru
      "Widgets": "Widgets",
      "temp": {
        "*": {
          "Features": {
            // walk thru the doubly nested structure an
            //  now accumulate all non-null itens into 
            //  the the final Features array.
            "*": "Features[]"
          }
        }
      }
    }
  }
]

Наконец, он работает с приведенной ниже спецификацией, НО имеет нежелательный побочный эффект: он оставляет пустые массивы по умолчанию. Есть ли способ удалить пустые массивы или иным образом пометить их на шаге по умолчанию, чтобы их можно было удалить? Я проверил эту проблему с GitHub, но не уверен, как перевести ее в массивы строк. У кого-нибудь есть лучшее решение?

[
  // First fill in default value for "MenuItems" since not all Features have it.
  {
    "operation": "default",
    "spec": {
      "Widgets[]": {
        "*": {
          "Features[]": {
            "*": {
              "MenuItems": []
            }
          }
        }
      }
    }
  },
  {
    // Extract the Features' properties into arrays. The defaults added above ensure that we can merge the arrays into Feature objects as in this example: 
    // https://github.com/bazaarvoice/jolt/blob/master/jolt-core/src/test/resources/json/shiftr/mergeParallelArrays2_and-do-not-transpose.json.
    "operation": "shift",
    "spec": {
      "Widgets": {
        "*": {
          "Id": "Widgets[&1].Id",
          "PetFriendly": "Widgets[&1].PetFriendly",
          "Features": {
            "*": {
              "@(2,Id)": "temp.WidgetId",
              "Name": "temp.Name",
              "Type": "temp.Type",
              "MenuItems": "temp.MenuItems[]"
            }
          }
        }
      }
    }
  },
  // Finally merge the arrays into Feature objects.
  {
    "operation": "shift",
    "spec": {
      "Widgets": "Widgets",
      "temp": {
        "WidgetId": {
          "*": "Features[&0].WidgetId"
        },
        "Name": {
          "*": "Features[&0].Name"
        },
        "Type": {
          "*": "Features[&0].Type"
        },
        "MenuItems": {
          "*": "Features[&0].MenuItems"
        }
      }
    }
  }
]

Результат:

{
  "Widgets": [
    {
      "Id": "1",
      "PetFriendly": "True"
    },
    {
      "Id": "2",
      "PetFriendly": "True"
    },
    {
      "Id": "3",
      "PetFriendly": "False"
    },
    {
      "Id": "4",
      "PetFriendly": "False"
    }
  ],
  "Features": [
    {
      "WidgetId": "1",
      "Name": "Easy Button",
      "Type": "Button",
      "MenuItems": []
    },
    {
      "WidgetId": "1",
      "Name": "Lunch Lever",
      "Type": "Food Service",
      "MenuItems": [ "Pizza", "Cheezburger" ]
    },
    {
      "WidgetId": "3",
      "Name": "Missles",
      "Type": "Attack",
      "MenuItems": []
    },
    {
      "WidgetId": "4",
      "Name": "Bombs",
      "Type": "Attack",
      "MenuItems": [ "Rat Poison" ]
    }
  ]
}
Другие вопросы по тегам