0

Given a JSON array of:

[
  {
      "id": 1,
      "name": "abc"
  },
  {
      "id": 2
  },
  {
      "id": 3,
      "name": "def"
  }
]

I would expect:

JArray jArray = JArray.Parse(json);
dynamic value = jArray.SelectTokens("$[?(@['name'] == null || @['name'] == 'abc')]");

to produce:

[
  {
    "id": 1,
    "name": "abc"
  },
  {
    "id": 2
  }
]

This tests correctly using a variety of online JsonPath testers. But when I run it with Json.NET, I am getting:

[
  {
    "id": 1,
    "name": "abc"
  }
]

Is it possible for me to change the JsonPath to handle this? Is it the null in the query that is the problem?

For clarity, I need to use JsonPath because it is stored in a configuration file and applied dynamically.

2 Answers 2

2

I expect that Newtsoft is considering absence to be different from "present with a null value," whereas the others you've tried consider them to be the same.

I imagine if you update the path to

$[?(!@['name'] || @['name'] == null || @['name'] == 'abc')]

it might work for you.

Alternatively, updating the data to

[
  {
      "id": 1,
      "name": "abc"
  },
  {
      "id": 2,
      "name": null
  },
  {
      "id": 3,
      "name": "def"
  }
]

would also yield the middle item.


We haven't defined this yet in the specification effort, but it's a good one. I'll raise that in an issue.

You can also see there's no consensus among libraries with this test.

Sign up to request clarification or add additional context in comments.

2 Comments

Unfortunately Newtonsoft treats ! as an unexpected character if I use that syntax. Good suggestion though.
0

With LINQ to JSON you can solve the same problem like this:

var json = File.ReadAllText("sample.json");

var semiParsedJson = JArray.Parse(json);
var filteredJson = from item in semiParsedJson
                   let name = (string)item["name"]
                   where name == null || name == "abc"
                   select item;

Console.WriteLine(new JArray(filteredJson));

The output will be as expected:

[
  {
    "id": 1,
    "name": "abc"
  },
  {
    "id": 2
  }
]

2 Comments

Yes, another good suggestion. In my case, I need to use JsonPath because it is stored in a configuration file and applied dynamically.
@maxmoore14 Could you please include this valuable information into your question? To avoid further alternative suggestions :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.