skip to Main Content

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/)

2

Answers


  1. 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]
    
    Login or Signup to reply.
  2. 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.

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