Cliff Pennalligen
Cliff Pennalligen

Reputation: 423

Json Path - get all but last element of an array

I have a JSON array:

[
    1,
    2,
    3,
    4
]

I want to create a Json Path expression that returns all but the last element of the array, i.e. the result is:

[
    1,
    2,
    3
]

There are lots of examples of first N elements and last N elements, but not the above. I can't work out the syntax.

I am using System.Text.Json with JsonPath.Net (https://www.nuget.org/packages/JsonPath.Net/)

Upvotes: -1

Views: 100

Answers (2)

dbc
dbc

Reputation: 116794

JsonPath.NET implements RFC 9535, and RFC 9535 includes the Array Slice Selector [start:end:step]. When start or end are negative, they are interpreted as offsets from the array end:

Slice expression parameters start and end are not directly usable as slice bounds and must first be normalized. Normalization for this purpose is defined as:

FUNCTION Normalize(i, len):
  IF i >= 0 THEN
    RETURN i
  ELSE
    RETURN len + i
  END IF

Thus "$[0:-1]" should return all but the last element of the array, and JsonPath.NET does seem to implement this correctly:

var jsonArray = JsonSerializer.SerializeToNode(new int[] { 1, 2, 3, 4} )!.AsArray();

var path = JsonPath.Parse("$[0:-1]");
var results = path.Evaluate(jsonArray);

var newArray = JsonSerializer.SerializeToNode(results.Matches.Select(m => m.Value))!.AsArray(); // [1,2,3]

Assert.That(new int [] { 1, 2, 3 }.SequenceEqual(newArray.Deserialize<int []>()!)); // PASSES

Demo fiddle here.

Upvotes: 1

gregsdennis
gregsdennis

Reputation: 8428

Syntax to support your use case doesn't exist in the JSON Path spec. You need a way to get the index of the current value.

We have an open issue for a proposal to add that in a potential next version, https://github.com/ietf-wg-jsonpath/draft-ietf-jsonpath-base/issues/516.

The other difficult part in this particular case is that you'd need to get the length of the parent array. Again, there's not a syntax for that.


Assuming you built custom functions key() and parent(), and you enabled math operations (in the parsing options), you might be able to do something like this:

$[key(@)<length(parent(@))-1]

Upvotes: 0

Related Questions