Matching a JSON object with an instance

Suppose I have a DTO:

class C {
    String a;
    String b;
}

      

And I have JSON:

{
    "c" : {
        "a" : "aaa",
        "b" : "bbb"
    }
}

      

What I want to do is do the following test:

C expected = new C("aaa","bbb");
mockMvc.perform(get("url"))
    .andExpect(jsonPath("$.c", is(expected)));

      

He fails. If I serialize expected

to JSON first and then try to match it fails again because it is a string. Is it possible?

+3


source to share


2 answers


Always remember: there is no such thing as a "JSON object". JSON is a serialization format for objects. JSON is always a string. You can convert from object to JSON and back (and therefore from object to string and back). But

{ "a": "b" }

      

- a JavaScript object, not JSON (even if it looks very similar).

This is actually the answer to your question: when you serialize expected

, you get JSON (transport format, i.e. string). This is not what tests jsonPath()

. jsonPath()

checks JavaScript types.

This blog post suggests that you need to validate each field separately:



.andExpect(jsonPath("$.c.a", is(expected.a)))
.andExpect(jsonPath("$.c.b", is(expected.b)));

      

which is tedious. What you need is a) set up your JSON structure to use a mapping system that sorts the keys, and b) you need to figure out what type it jsonPath("$.c", ...)

returns - this is probably the type your JSON framework uses to represent common JavaScript objects.

Then the check looks like this:

C c = new C("aaa","bbb");
String serialized = JSON.serialize(c); // to string
JSObject expected = JSON.parse(serialized); // to generic JavaScript object
mockMvc.perform(get("url"))
    .andExpect(jsonPath("$.c", is(expected)));

      

Note that this only works if it JSObject

has the correct implementation for equals()

.

+2


source


If you can afford to modify your "C" class to add it to the "equals" and modify your JSON file a bit, I would suggest you convert your JSON string to an instance of "C". This can be done with a good JSON-ifier (Jackson or GSON). Then you just need to compare two instances. Some examples with GSON:

class C {
    String a;
    String b;
    public boolean equals(C obj) { return a.equals(obj.a) && b.equals(obj.b); }
}
// Your JSON file should look like that
{
    "a" : "aaa",
    "b" : "bbb"
}
// So the test is simple
C expected = new C("aaa","bbb");
C json = gson.fromJson(jsonString, C.class); 
if (expected.equals(json)) {
    // Do whatever you want here
}

      

If you can't afford to change the JSON file, just create another class that will contain your main class, for example:



class Wrapper {
    C c;
}
Wrapper jsonW = gson.fromJson(jsonString, Wrapper.class);
C json = jsonW.c;
...

      

If you cannot afford adding equals statement, I suggest creating a JSON string based on instance 2 "C" instances and comparing the strings. Your jsonString becomes a real "C" object (json) and then ends with a new string (jsonStr).

String expectedStr = gson.toJson(expected);
String jsonStr = gson.toJSON(json);
if (expectedStr.equals(jsonStr)) {
    // Do whatever you want here
}

      

+1


source







All Articles