Assert with a json that contains a json

Hi !

I would like to ask you if some tools already exists as I wanted to go further with tests on json for example. There are assert_json! and validators that allow you to check the consistency of some of the fields. Is there a way to check if a json contains a value? For example with the data not known in advance of a json like this?

{
    "data": {
        "A": {
            "B": {
                "C": [
                    {
                        "id": "1",
                        "description": "desc 1"
                    },
                    {
                        "id": "2",
                        "description": "desc 2"
                    }
                ]
            }
        }
    }
}

I just want to check if the following is in the array ? Like if the first one contains this one...

{
    "data": {
        "A": {
            "B": {
                "C": [
                    {
                        "id": "1",
                        "description": "desc 1"
                    }
                ]
            }
        }
    }
}

Kind of :

let json1 = // first json
let json2 = // second json

json1.contains(json2) -> bool ?

Maybe, I can have other example where it is not an array we check... Just that one contains the data of the other as least... Or the reverse operation... the second is in the first one ?

json2.is_in(json1) -> bool ?

There is JSONpath, which is a fairly standard way of selecting JSON elements. There's at least one jsonpath rust crate.

A lot of people are more familiar with jq which is its own command line tool. It's a C API so there's a jq rust crate.

I think you could do what you need to with either of those, but I'm not sure of the exact syntax to filter arrays in either.

In jq you can use the contains function:

> jq -n "[0, 1, 2] | contains([1, 2])"
true
> jq -n "[0, 1, 2] | contains([3, 4])"
false

This even works for the whole object presented by OP:

> X='{
>     "data": {
>         "A": {
>             "B": {
>                 "C": [
>                     {
>                         "id": "1",
>                         "description": "desc 1"
>                     },
>                     {
>                         "id": "2",
>                         "description": "desc 2"
>                     }
>                 ]
>             }
>         }
>     }
> }'

> Y='{
>     "data": {
>         "A": {
>             "B": {
>                 "C": [
>                     {
>                         "id": "1",
>                         "description": "desc 1"
>                     }
>                 ]
>             }
>         }
>     }
> }'

> jq -n "$X | contains($Y)"
true
> jq -n "$Y | contains($X)"
false
2 Likes

Thank you very much. I will try all of that tomorow !!

When looking for documentation of these crate, I discover this one :
assert_json_diff = "2.0.2"

Maybe the assert include could do the same staff...

But it is the first time, I can't use this crate...

 Updating crates.io index
error: no matching package found
error: no matching package found
searched package name: `assert_json_diff`
perhaps you meant:      assert-json-diff
location searched: crates.io index

I do not have connection probrem... Do you know how we can undestand why we can't use this crate ? The name correct by the way...

The crate is called assert-json-diff with dashes, not underscores.

1 Like

Yes, I just try in case... An it works... Documentation has not the same name...

I think of the docs.rs URLs like this:

https://docs.rs/assert-json-diff/latest/assert_json_diff/
                ^^^^^^^^^^^^^^^^        ^^^^^^^^^^^^^^^^
                |                       |> how to spell when using crate in your code
                |
                |> how to spell when declaring crate as dependency in `Cargo.toml`
2 Likes

Thanks !

I am trying the assert_json_include! functionnality...
But the message indicates that it seems to look for an equal, not an include ... ?
I will investigate...

json atoms at path "(root)" are not equal:
    expected:
        "{\"data\":{\"A\":{\"B\":{\"C\":[{\"id\":\"1\",\"description\":\"desc1\"}]}}}}"
    actual:
        "{\"data\":{\"A\":{\"B\":{\"C\":[{\"id\":\"1\",\"description\":\"desc1\"},{\"id\":\"2\",\"description\":\"desc2\"}]}}}}"

Try reversing the arguments. Looks to me like you are trying to assert that the subset contains the superset, instead of the other way around.

I try in case of in the way.

I read again documentation " assert_json_include allows extra data in actual but not in expected."

It should be good. I will try with other json to see if there is another problem I don't see now...

I try

assert_json_matches! with Config::new(CompareMode::Inclusive)

It is supposed to be the same... and fail also...

With others tests, it is perfect...
I think my json has a problem...
Thanks for your time :wink:

This code works :

 #[test]
    fn test_assert_json(){
        assert_json_matches!(
            json!({ "a": { "b": {"c": [1, 2] } }}),
            json!({ "a": { "b" : { "c": [1]}} }),
            Config::new(CompareMode::Inclusive),
        );
        
        // Is the same as this
        assert_json_include!(
            actual: json!({ "a": { "b": {"c": [1, 2] } }}),
            expected: json!({ "a": { "b" : { "c": [1]}} })
        );
    }

But not this one. Maybe, all the precedent values must be included... just not a value in an array... ?

#[test]
    fn test_assert_json(){
        assert_json_matches!(
            json!({ "a": { "b": {"c": [1, 2] } }}),
            json!({ "a": { "b" : { "c": [2]}} }),
            Config::new(CompareMode::Inclusive),
        );
        
        // Is the same as this
        assert_json_include!(
            actual: json!({ "a": { "b": {"c": [1, 2] } }}),
            expected: json!({ "a": { "b" : { "c": [2]}} })
        );
    }

Problem solved !

I realise my argument are string.
If I use :

json!(my_string)

It fails...

But with this, it works :

 serde_json::from_str::<serde_json::Value>(&my_string).unwrap()

I think I will look after other crate after testing this one because, it is not like a real "contains"...

json_test - Rust seems to have a lot of feature interessing too.