0

Given the following JSON:

{
    "pos":123,
    "name":"Bla"
}

I'm trying to validate that the JSON provided has a name property with the value Bla

Following the documentation on json.net I established that this should work:

$.[?(@.name == 'Bla')]

I validated this idea on https://jsonpath.herokuapp.com/ and it seems to return the object if it is true, and nothing if it isn't

However, when trying the same in json.net it never seems to return a valid JToken.

Example code here: https://dotnetfiddle.net/0agXyZ (passing true into SelectToken says it should throw an error if the result is not found, I'm not seeing this either).

Is this something I'm doing wrong here?

What I'm trying to do is write a test That will allow developers to specify expected JSON to be returned from their tests, so it made sense to me that if there was a way to provide them a way to input a validation string in JSON path format I can hide the details of this validation in my framework.

Thanks.

1
  • 1
    Newtonsoft's SelectToken() is only designed to work for objects inside arrays, not for root objects or objects inside other objects. See: JSONPath scripts not executing correctly for objects #1256: I'm not sure about this. Nothing in the JSONPath says that filters should apply to objects. Sometimes workarounds can be found, see here or here. Commented Jun 1, 2022 at 16:16

2 Answers 2

2

As indicated by @dbc in the comment above, the JSONPath search filter is meant for arrays. You can still go after an individual property in an object just to see if it exists.

Expanding the example posted at dotnetfiddle.

using System;
using System.Xml;
using System.Xml.Linq;
using System.Linq;
using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
                    
public class Program
{
    public static void Main()
    {
        var json = @"{'pos':123,'name':'Bla'}";
        var jobj = JObject.Parse(json);

        Console.WriteLine("Looking for 'name'");
        JToken token = jobj.SelectToken("$.name");
        if (token == null) Console.WriteLine("error");
        Console.WriteLine(token);
        
        Console.WriteLine("Looking for 'names'");
        token = jobj.SelectToken("$.names");
        if (token == null) Console.WriteLine("error");
        Console.WriteLine(token);

        
        var json2 = @"{
            'data': [
                {
                    'pos':123,
                    'name':'Bla'
                },
                {
                    'pos':123,
                    'name':'Bla2'
                },
                {
                    'pos':123,
                    'name':'Bla3'
                }
            ]
        }";
        var jobj2 = JObject.Parse(json2);

        Console.WriteLine("Looking for 'name == 'Bla2'' in array.");
        JToken token2 = jobj2.SelectToken("$.data[?(@.name == 'Bla2')]");
        if (token2 == null) Console.WriteLine("error");
        Console.WriteLine(token2);
    }
}

The result is:

Looking for 'name'
Bla
Looking for 'names'
error

Looking for 'name == 'Bla2'' in array.
{
  "pos": 123,
  "name": "Bla2"
}
Sign up to request clarification or add additional context in comments.

1 Comment

Ahh this makes sense. thanks for such a comprehensive answer!
1

json path is not valid with jobject, it is used with collections. For your json you can use this

var json=@"{
        ""pos"":123,
        ""name"":""Bla""
        }";
    
    var jsonObject=JObject.Parse(json);
    bool thereIsName =(string)jsonObject.SelectToken("name")=="Bla"; //True

you can use a json path for a similar json

var json=@"[{
    ""pos"":123,
    ""name"":""Bla""
    }]";

var jsonArray=JArray.Parse(json);

bool thereIsName = jsonArray.SelectToken("$[?(@.name == 'Bla')]")!=null; //True

Comments

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.