Small library for those who have a hard time understanding the complexity of JSON Path.
Have you ever met such a JSON Path expression?
$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]
Pretty isn’t it? Wouldn’t it be better to just read:
assertThat(jsonAsString).array().field("place").field("bounding_box").array("coordinates").array().contains(38.791645).value()
JSON Assert to the rescue!
<dependency>
<groupId>com.toomuchcoding.jsonassert</groupId>
<artifactId>jsonassert</artifactId>
<version>${jsonassert.version}</version>
<scope>test</scope>
</dependency>
testImplementation "com.toomuchcoding.jsonassert:jsonassert:${jsonassertVersion}"
The library has a couple of main classes. One is JsonAssertion
that gives you public static methods:
public static JsonVerifiable assertThat(String body)
NOTE! The aforementioned version caches the DocumentContext
for the provided JSON.
and
public static JsonVerifiable assertThat(DocumentContext parsedJson)
Both these methods give return the public JsonVerifiable
interface which is a fluent interface with which you can build your
JSON path expression. Please check the Javadocs of that file for more information.
As you could see it’s not that easy to build a JSON Path. With JSON Assert you can use the JsonPath
class to finally
build the JSON Paths yourself! This is the contract for the JsonPath
class:
/**
* Returns a builder of {@link JsonVerifiable} with which you can build your
* JSON Path. Once finished just call {@link JsonVerifiable#jsonPath()} to get
* JSON Path as String.
*/
public static JsonVerifiable builder()
and when you call:
JsonPath.builder().field("some").field("nested").array("withlist").contains("name").isEqualTo("name1").jsonPath();
you will receive $.some.nested.withlist[*][?(@.name == 'name1')]
String.
Wouldn’t it be great to retrieve the value from the JSON via the JSON Path? There you go!
given:
String json = ''' [ {
"some" : {
"nested" : {
"json" : "with value",
"anothervalue": 4,
"withlist" : [
{ "name" :"name1"} ,
{"name": "name2"},
{"anothernested": { "name": "name3"} }
]
}
}
},
{
"someother" : {
"nested" : {
"json" : true,
"anothervalue": 4,
"withlist" : [
{ "name" :"name1"} , {"name": "name2"}
],
"withlist2" : [
"a", "b"
]
}
}
}
]
'''
expect:
com.toomuchcoding.jsonassert.JsonPath.builder(json).array().field("some").field("nested").field("json").read(String) == 'with value'
com.toomuchcoding.jsonassert.JsonPath.builder(json).array().field("some").field("nested").field("anothervalue").read(Integer) == 4
assertThat(json).array().field("some").field("nested").array("withlist").field("name").read(List) == ['name1', 'name2']
assertThat(json).array().field("someother").field("nested").array("withlist2").read(List) == ['a', 'b']
assertThat(json).array().field("someother").field("nested").field("json").read(Boolean) == true
All thanks to the JsonReader
interface:
/**
* Returns the value from the JSON, based on the created JSON Path. If the result is an
* JSON Array and has a single value then that value is returned. If that's an array with
* greater number of results then that array is returned.
*/
<T> T read(Class<T> clazz);
Just add it as your dependency (Example for Gradle)
testCompile 'com.toomuchcoding.jsonassert:jsonassert:{lib_version}'
JSON Assert is really lightweight. It has only one dependency
compile "com.jayway.jsonpath:json-path:2.2.0"
For the JSON
{
"some" : {
"nested" : {
"json" : "with \"val'ue",
"anothervalue": 4,
"withlist" : [
{ "name" :"name1"} ,
{"name": "name2"}
]
}
}
}
The following is true
JSON Assert expressions:
JsonAssertion.assertThat(json).field("some").field("nested").field("anothervalue").isEqualTo(4)
JsonAssertion.assertThat(json).field("some").field("nested").array("withlist").contains("name").isEqualTo("name1")
JsonAssertion.assertThat(json).field("some").field("nested").array("withlist").contains("name").isEqualTo("name2")
JsonAssertion.assertThat(json).field("some").field("nested").field("json").isEqualTo("with \"val'ue")
Respective JSON Path expressions:
$.some.nested[?(@.anothervalue == 4)]
$.some.nested.withlist[*][?(@.name == 'name1')]
$.some.nested.withlist[*][?(@.name == 'name2')]
$.some.nested[?(@.json == 'with "val\\'ue')]
For the JSON
[{
"place":
{
"bounding_box":
{
"coordinates":
[[
[-77.119759,38.995548],
[-76.909393,38.791645]
]]
}
}
}]
The following is true
JSON Assert expressions:
JsonAssertion.assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().arrayField().contains(38.995548).value()
JsonAssertion.assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().arrayField().contains(-77.119759).value()
JsonAssertion.assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().arrayField().contains(-76.909393).value()
JsonAssertion.assertThat(json11).array().field("place").field("bounding_box").array("coordinates").array().arrayField().contains(38.791645).value()
Respective JSON Path expressions:
$[*].place.bounding_box.coordinates[*][*][?(@ == 38.995548)]
$[*].place.bounding_box.coordinates[*][*][?(@ == -77.119759)]
$[*].place.bounding_box.coordinates[*][*][?(@ == -76.909393)]
$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]
Since Jayway’s library is quite old, it includes old versions of libraries such as asm
. We’ve noticed issues
in other projects that include newer versions of those libraries. The user has 2 options, either exclude the
transitive dependencies and hope that the newer ones will still work or use the new jsonassert-shade
library
that comes with shaded versions of all the dependencies.
There is a possibility to use JSON Assert via AssertJ. Regardless of which version you’ll choose you have the same class that you can use to start the fluent assertion
The standard version
com.toomuchcoding.jsonassert.JsonAssertions.assertThat(DocumentContext context);
com.toomuchcoding.jsonassert.JsonAssertions.assertThat(JsonVerifiable jsonVerifiable);
or the BDD version
com.toomuchcoding.jsonassert.BDDJsonAssertions.then(DocumentContext context);
com.toomuchcoding.jsonassert.BDDJsonAssertions.then(JsonVerifiable jsonVerifiable);
Just add
testCompile 'com.toomuchcoding.jsonassert:jsonassert-assertj-java7:{lib_version}'
-
Convert all project imports from
com.blogspot.toomuchcoding:jsonassert
tocom.toomuchcoding.jsonassert:jsonassert
-
Convert all code imports from
com.blogspot.toomuchcoding.jsonassert
tocom.toomuchcoding.jsonassert