marcingrzejszczak / Jsonassert
Programming Languages
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
tocom.toomuchcoding.jsonassert:jsonassert
- Convert all code imports from
com.blogspot.toomuchcoding.jsonassert
tocom.toomuchcoding.jsonassert
= Contact