skip to Main Content

I’m looking for a solution of grouping elements from a flat hierarchy into a encapsulated one with the help of JSONata.

Given that I have the following input data:

[  
  {
    "restaurantName": "Pizza Place",
    "restaurantId": "1",
    "dishName": "Margherita  Pizza",
    "dishId": "A"
  },
  {
    "restaurantName": "Pizza Place",
    "restaurantId": "1",
    "dishName": "Four Cheese Pizza",
    "dishId": "B"
  },
  {
    "restaurantName": "Pizza Palace",
    "restaurantId": "2",
    "dishName": "Margherita  Pizza",
    "dishId": "A"
  },
  {
    "restaurantName": "Pizza Palace",
    "restaurantId": "2",
    "dishName": "Four Cheese Pizza",
    "dishId": "B"
  },
  {
    "restaurantName": "Pizza Palace",
    "restaurantId": "2",
    "dishName": "Pepperoni Pizza",
    "dishId": "C"
  }
]

I want to group them together by restaurants like so:

[
  {
    "restaurantName": "Pizza Place",
    "restaurantId": "1",
    "menu": [
      {
        "dishName": "Margherita  Pizza",
        "dishId": "A"
      },
      {
        "dishName": "Four Cheese Pizza",
        "dishId": "B"
      }
    ]
  },
  {
    "restaurantName": "Pizza Palace",
    "restaurantId": "2",
    "menu": [
      {
        "dishName": "Margherita  Pizza",
        "dishId": "A"
      },
      {
        "dishName": "Four Cheese Pizza",
        "dishId": "B"
      },
      {
        "dishName": "Pepperoni Pizza",
        "dishId": "C"
      }
    ]
  }
]

I already tried to find a solution with the help of the JSONata Exerciser and this solution seems to work on the reduced input data set but as soon as I use the full data set (just more restaurants and more dishes) I can a time out exception (maybe due to infinite loops):

$distinct(
        $map($distinct($), function($v0, $i, $a) {
        {
            "restaurantName":$v0.restaurantName,
            "restaurantId": $v0.restaurantId,
            "menu":$distinct($filter($$, function($v1,$i,$a) {$v1.restaurantId = $v0.restaurantId}).{
                "dishName": dishName,
                "dishId": dishId
            })
        }
    })
)

If anyone has a solution and an explanation on how to best achieve this with JSONata this would be of great help.

Greetings

2

Answers


  1. You can group by restaurantId into an object, and then iterate over object entries using the $each function:

    $${
      restaurantId: $
    } ~> $each(function($objects, $id) {{
      "restaurantId": $id,
      "restaurantName": $objects[0].restaurantName,
      "menu": $objects.{
        "dishName": dishName,
        "dishId": dishId
      }
    }})
    

    Check it out on the Stedi Playground: https://stedi.link/qJhXW0h

    Login or Signup to reply.
  2. This seems to work and I feel is a little more intuitive to follow:

    ${
        (restaurantName & restaurantId): {
            "restaurantName": $[0].restaurantName,
            "restaurantId": $[0].restaurantId,
            "menu": $.$sift(function($_, $k){$k~>/^dish/})
        }
    }.*
    

    Grouping by restaurantName and restaurantId, we map the name and id for each group and pick out the dish* properties to build out the menu. Then map to the values of the grouping.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search