Search code examples
jsonjsonpath

JSON Path: get first children in an object


Got an API response looking like this:

{
  "data": {
    "unpredictable_name_1": {
      "inner_data": [
        {
          "wanted_data": "something1",
          "other_data": 1000
        },
        {
          "wanted_data": "something2",
          "other_data": 1001
        }
      ],
      "something_else_1": "some_data"
    },
    "unpredictable_name_2": {
      "inner_data": [
        {
          "wanted_data": "something1",
          "other_data": 1000
        },
        {
          "wanted_data": "something2",
          "other_data": 1001
        }
      ]
    }
  }
}

I need a JSON path query returning only this:

[
  {
    "wanted_data": "something1",
    "other_data": 1000
  },
  {
    "wanted_data": "something2",
    "other_data": 1001
  }
]

If use this $..inner_data, I got both inner_data arrays, and I found no way to get only the first one. (Tested here: https://jsonpath.curiousconcept.com/). $..inner_data[0] does not work as it gives me twice the same array element from both objects.


Solution

  • This ...

    $.data.unpredictable_name_1.inner_data
    

    ... will return:

    [
       {
          "wanted_data" : "something1",
          "other_data" : 1000
       },
       {
          "wanted_data" : "something2",
          "other_data" : 1001
       }
    ]
    

    But I suspect that you deliberately choose the attribute name unpredictable_name_1 to suggest that you won't know the name of that attribute and hence cannot rely on including that name in your json path.

    I think you want to get the entire content of the inner_data attribute of the first attribute of data but since the top level attributes of data are not elements in an array they have no concept of first or second or any position.

    To put it another way: unpredictable_name_1 is only first in your view of the document, JsonPath has no concept of it being the first attribute of data therefore JsonPath cannot find that attribute on the basis of position.

    By contrast, inner_data is an array so it can be addressed by position. For example: $..inner_data[0] will return the first element of each of the inner_data attributes. JsonPath can apply the positional operator [0] because inner_data is an array.

    So, JsonPath cannot do this: get the entire content of the inner_data attribute of the first attribute of data because the top level attributes in data are not members of an array. In order to get that data from the given JSON you would need to deserialise the JSON into some structure (such as a Map) using a JSON library (in the Java realm this would probably be Gson or Jackson, you don't mention your language in the OP but there's likey to a JSON de/serialisation library in whatever language you are using) and you would then apply your own definition of first to that structure.