image::https://github.com/marcingrzejszczak/jsonassert/workflows/Build/badge.svg?style=svg["Build",link="https://github.com/marcingrzejszczak/jsonassert/actions"]
image::https://maven-badges.herokuapp.com/maven-central/com.toomuchcoding.jsonassert/jsonassert/badge.svg?style=plastic[Maven Central, link="https://maven-badges.herokuapp.com/maven-central/com.toomuchcoding.jsonassert/jsonassert"]
image::https://badges.gitter.im/Join%20Chat.svg[Gitter, link="https://gitter.im/marcingrzejszczak/jsonassert?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"]
= JSON Assert
Small library for those who have a hard time understanding the complexity of JSON Path.
:toc:
:toc-placement!:
toc::[]
= Rationale
Have you ever met such a JSON Path expression?
[source]
$[].place.bounding_box.coordinates[][*][?(@ == 38.791645)]
Pretty isn't it? Wouldn't it be better to just read:
[source,java]
assertThat(jsonAsString).array().field("place").field("bounding_box").array("coordinates").array().contains(38.791645).value()
JSON Assert to the rescue!
== Fast intro
=== Adding to your project
.pom.xml (Maven)
<dependency>
<groupId>com.toomuchcoding.jsonassert</groupId>
<artifactId>jsonassert</artifactId>
<version>${jsonassert.version}</version>
<scope>test</scope>
</dependency>
.build.gradle (Gradle)
testImplementation "com.toomuchcoding.jsonassert:jsonassert:${jsonassertVersion}"
=== Assertions
The library has a couple of main classes. One is JsonAssertion
that gives you public static methods:
[source,java]
public static JsonVerifiable assertThat(String body)
NOTE! The aforementioned version caches the DocumentContext
for the provided JSON.
and
[source,java]
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.
=== Building JSON Paths
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:
[source,java]
/**
- 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:
[source,java]
JsonPath.builder().field("some").field("nested").array("withlist").contains("name").isEqualTo("name1").jsonPath();
you will receive $.some.nested.withlist[*][?(@.name == 'name1')]
String.
=== Retrieving JSON Path value (since 0.4.0)
Wouldn't it be great to retrieve the value from the JSON via the JSON Path? There you go!
[source,groovy]
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:
[source,java]
/**
- 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 read(Class clazz);
----
== How to add it
Just add it as your dependency (Example for Gradle)
[source,groovy,subs="attributes,verbatim"]
testCompile 'com.toomuchcoding.jsonassert:jsonassert:{lib_version}'
== Dependencies
JSON Assert is really lightweight. It has only one dependency
[source,groovy]
compile "com.jayway.jsonpath:json-path:2.2.0"
== Examples
=== Example 1
For the JSON
[source,json]
{
"some" : {
"nested" : {
"json" : "with \"val'ue",
"anothervalue": 4,
"withlist" : [
{ "name" :"name1"} ,
{"name": "name2"}
]
}
}
}
The following is true
JSON Assert expressions:
[source,java]
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:
[source]
$.some.nested[?(@.anothervalue == 4)]
$.some.nested.withlist[][?(@.name == 'name1')]
$.some.nested.withlist[][?(@.name == 'name2')]
$.some.nested[?(@.json == 'with "val\'ue')]
=== Example 2
For the JSON
[source,json]
[{
"place":
{
"bounding_box":
{
"coordinates":
[[
[-77.119759,38.995548],
[-76.909393,38.791645]
]]
}
}
}]
The following is true
JSON Assert expressions:
[source,java]
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:
[source]
$[].place.bounding_box.coordinates[][][?(@ == 38.995548)]
$[].place.bounding_box.coordinates[][][?(@ == -77.119759)]
$[].place.bounding_box.coordinates[][][?(@ == -76.909393)]
$[].place.bounding_box.coordinates[][][?(@ == 38.791645)]
=== More examples
More examples can be found in the JsonAssertionSpec
in the test sources
= Additional features
== Shaded library (since 0.5.0)
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.
== AssertJ integration (since 0.2.0)
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
[source,java]
com.toomuchcoding.jsonassert.JsonAssertions.assertThat(DocumentContext context);
com.toomuchcoding.jsonassert.JsonAssertions.assertThat(JsonVerifiable jsonVerifiable);
or the BDD version
[source,java]
com.toomuchcoding.jsonassert.BDDJsonAssertions.then(DocumentContext context);
com.toomuchcoding.jsonassert.BDDJsonAssertions.then(JsonVerifiable jsonVerifiable);
=== AssertJ 2.x
Just add
[source,groovy,subs="attributes,verbatim"]
testCompile 'com.toomuchcoding.jsonassert:jsonassert-assertj-java7:{lib_version}'
=== AssertJ 3.x
Just add
[source,groovy,subs="attributes,verbatim"]
testCompile 'com.toomuchcoding.jsonassert:jsonassert-assertj-java8:{lib_version}'
= Migrations
== From 0.1.x -> 0.2.0
- Convert all project imports from
com.blogspot.toomuchcoding:jsonassert
to com.toomuchcoding.jsonassert:jsonassert
- Convert all code imports from
com.blogspot.toomuchcoding.jsonassert
to com.toomuchcoding.jsonassert
= Contact
https://gitter.im/marcingrzejszczak/jsonassert[Gitter chat]