未验证 提交 58812d8e 编写于 作者: K kallestenflo 提交者: GitHub

Merge pull request #624 from json-path/master

release master changes on production 
......@@ -13,3 +13,4 @@ TODO
gradle.properties
build
bin/
out/
......@@ -3,7 +3,7 @@ language: java
sudo: false
jdk:
- oraclejdk7
- openjdk8
cache:
directories:
......
......@@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Copyright 2017 Jayway
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
......
Jayway JsonPath 2.2.0
Jayway JsonPath
=====================
**A Java DSL for reading JSON documents.**
[![Build Status](https://travis-ci.org/jayway/JsonPath.svg?branch=master)](https://travis-ci.org/jayway/JsonPath)
[![Build Status](https://travis-ci.org/json-path/JsonPath.svg?branch=master)](https://travis-ci.org/json-path/JsonPath)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.jayway.jsonpath/json-path/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.jayway.jsonpath/json-path)
[![Javadoc](https://javadoc-emblem.rhcloud.com/doc/com.jayway.jsonpath/json-path/badge.svg)](http://www.javadoc.io/doc/com.jayway.jsonpath/json-path)
[![Javadoc](https://www.javadoc.io/badge/com.jayway.jsonpath/json-path.svg)](http://www.javadoc.io/doc/com.jayway.jsonpath/json-path)
Jayway JsonPath is a Java port of [Stefan Goessner JsonPath implementation](http://goessner.net/articles/JsonPath/).
News
----
05 Jul 2017 - Released JsonPath 2.4.0
26 Jun 2017 - Released JsonPath 2.3.0
29 Feb 2016 - Released JsonPath 2.2.0
22 Nov 2015 - Released JsonPath 2.1.0
......@@ -23,7 +27,6 @@ News
26 Sep 2014 - Released JsonPath 1.0.0
For details see [change log](changelog.md).
Getting Started
---------------
......@@ -34,11 +37,11 @@ JsonPath is available at the Central Maven Repository. Maven users add this to y
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.1.0</version>
<version>2.4.0</version>
</dependency>
```
If you need help ask questions at the [google group](https://groups.google.com/forum/#!forum/jsonpath).
If you need help ask questions at [Stack Overflow](http://stackoverflow.com/questions/tagged/jsonpath). Tag the question 'jsonpath' and 'java'.
JsonPath expressions always refer to a JSON structure in the same way as XPath expression are used in combination
with an XML document. The "root member object" in JsonPath is always referred to as `$` regardless if it is an
......@@ -74,13 +77,14 @@ Functions
Functions can be invoked at the tail end of a path - the input to a function is the output of the path expression.
The function output is dictated by the function itself.
| Function | Description | Output |
| :------------------------ | :----------------------------------------------------------------- |-----------|
| min() | Provides the min value of an array of numbers | Double |
| max() | Provides the max value of an array of numbers | Double |
| avg() | Provides the average value of an array of numbers | Double |
| stddev() | Provides the standard deviation value of an array of numbers | Double |
| length() | Provides the length of an array | Integer |
| Function | Description | Output |
| :------------------------ | :------------------------------------------------------------------ |-----------|
| min() | Provides the min value of an array of numbers | Double |
| max() | Provides the max value of an array of numbers | Double |
| avg() | Provides the average value of an array of numbers | Double |
| stddev() | Provides the standard deviation value of an array of numbers | Double |
| length() | Provides the length of an array | Integer |
| sum() | Provides the sum value of an array of numbers | Double |
Filter Operators
......@@ -88,19 +92,22 @@ Filter Operators
Filters are logical expressions used to filter arrays. A typical filter would be `[?(@.age > 18)]` where `@` represents the current item being processed. More complex filters can be created with logical operators `&&` and `||`. String literals must be enclosed by single or double quotes (`[?(@.color == 'blue')]` or `[?(@.color == "blue")]`).
| Operator | Description |
| :----------------------- | :---------------------------------------------------------------- |
| == | left is equal to right (note that 1 is not equal to '1') |
| != | left is not equal to right |
| < | left is less than right |
| <= | left is less or equal to right |
| > | left is greater than right |
| >= | left is greater than or equal to right |
| =~ | left matches regular expression [?(@.name =~ /foo.*?/i)] |
| in | left exists in right [?(@.size in ['S', 'M'])] |
| nin | left does not exists in right |
| size | size of left (array or string) should match right |
| empty | left (array or string) should be empty |
| Operator | Description |
| :----------------------- | :-------------------------------------------------------------------- |
| == | left is equal to right (note that 1 is not equal to '1') |
| != | left is not equal to right |
| < | left is less than right |
| <= | left is less or equal to right |
| > | left is greater than right |
| >= | left is greater than or equal to right |
| =~ | left matches regular expression [?(@.name =~ /foo.*?/i)] |
| in | left exists in right [?(@.size in ['S', 'M'])] |
| nin | left does not exists in right |
| subsetof | left is a subset of right [?(@.sizes subsetof ['S', 'M', 'L'])] |
| anyof | left has an intersection with right [?(@.sizes anyof ['M', 'L'])] |
| noneof | left has no intersection with right [?(@.sizes noneof ['M', 'L'])] |
| size | size of left (array or string) should match right |
| empty | left (array or string) should be empty |
Path Examples
......@@ -155,6 +162,7 @@ Given the json
| <a href="http://jsonpath.herokuapp.com/?path=$.store.*" target="_blank">$.store.*</a> | All things, both books and bicycles |
| <a href="http://jsonpath.herokuapp.com/?path=$.store..price" target="_blank">$.store..price</a> | The price of everything |
| <a href="http://jsonpath.herokuapp.com/?path=$..book[2]" target="_blank">$..book[2]</a> | The third book |
| <a href="http://jsonpath.herokuapp.com/?path=$..book[2]" target="_blank">$..book[-2]</a> | The second to last book |
| <a href="http://jsonpath.herokuapp.com/?path=$..book[0,1]" target="_blank">$..book[0,1]</a> | The first two books |
| <a href="http://jsonpath.herokuapp.com/?path=$..book[:2]" target="_blank">$..book[:2]</a> | All books from index 0 (inclusive) until index 2 (exclusive) |
| <a href="http://jsonpath.herokuapp.com/?path=$..book[1:2]" target="_blank">$..book[1:2]</a> | All books from index 1 (inclusive) until index 2 (exclusive) |
......@@ -234,17 +242,25 @@ String json = "{\"date_as_long\" : 1411455611975}";
Date date = JsonPath.parse(json).read("$['date_as_long']", Date.class);
```
If you configure JsonPath to use the `JacksonMappingProvider` you can even map your JsonPath output directly into POJO's.
If you configure JsonPath to use `JacksonMappingProvider` or `GsonMappingProvider` you can even map your JsonPath output directly into POJO's.
```java
Book book = JsonPath.parse(json).read("$.store.book[0]", Book.class);
```
To obtain full generics type information, use TypeRef.
```java
TypeRef<List<String>> typeRef = new TypeRef<List<String>>() {};
List<String> titles = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[*].title", typeRef);
```
Predicates
----------
There are three different ways to create filter predicates in JsonPath.
###Inline Predicates
### Inline Predicates
Inline predicates are the ones defined in the path.
......@@ -256,7 +272,9 @@ List<Map<String, Object>> books = JsonPath.parse(json)
You can use `&&` and `||` to combine multiple predicates `[?(@.price < 10 && @.category == 'fiction')]` ,
`[?(@.category == 'reference' || @.price > 10)]`.
###Filter Predicates
You can use `!` to negate a predicate `[?(!(@.price < 10 && @.category == 'fiction'))]`.
### Filter Predicates
Predicates can be built using the Filter API as shown below:
......@@ -289,7 +307,7 @@ Filter fooAndBar = filter(
);
```
###Roll Your Own
### Roll Your Own
Third option is to implement your own predicates
......@@ -307,7 +325,7 @@ List<Map<String, Object>> books =
Path vs Value
-------------
In the Goessner implementation a JsonPath can return either `Path` or `Value`. `Value` is the default and what all the examples above are returning. If you rather have the path of the elements our query is hitting this can be acheived with an option.
In the Goessner implementation a JsonPath can return either `Path` or `Value`. `Value` is the default and what all the examples above are returning. If you rather have the path of the elements our query is hitting this can be achieved with an option.
```java
Configuration conf = Configuration.builder()
......@@ -322,11 +340,20 @@ assertThat(pathList).containsExactly(
"$['store']['book'][3]['author']");
```
Set a value
-----------
The library offers the possibility to set a value.
```java
String newJson = JsonPath.parse(json).set("$['store']['book'][0]['author']", "Paul").jsonString();
```
Tweaking Configuration
----------------------
###Options
### Options
When creating your Configuration there are a few option flags that can alter the default behaviour.
**DEFAULT_PATH_LEAF_TO_NULL**
......@@ -368,10 +395,13 @@ This option configures JsonPath to return a list even when the path is `definite
```java
Configuration conf = Configuration.defaultConfiguration();
//Works fine
//ClassCastException thrown
List<String> genders0 = JsonPath.using(conf).parse(json).read("$[0]['gender']");
//PathNotFoundException thrown
List<String> genders1 = JsonPath.using(conf).parse(json).read("$[1]['gender']");
Configuration conf2 = conf.addOptions(Option.ALWAYS_RETURN_LIST);
//Works fine
List<String> genders0 = JsonPath.using(conf2).parse(json).read("$[0]['gender']");
```
**SUPPRESS_EXCEPTIONS**
<br/>
......@@ -380,10 +410,25 @@ This option makes sure no exceptions are propagated from path evaluation. It fol
* If option `ALWAYS_RETURN_LIST` is present an empty list will be returned
* If option `ALWAYS_RETURN_LIST` is **NOT** present null returned
**REQUIRE_PROPERTIES**
</br>
This option configures JsonPath to require properties defined in path when an `indefinite` path is evaluated.
```java
Configuration conf = Configuration.defaultConfiguration();
//Works fine
List<String> genders = JsonPath.using(conf).parse(json).read("$[*]['gender']");
Configuration conf2 = conf.addOptions(Option.REQUIRE_PROPERTIES);
###JsonProvider SPI
//PathNotFoundException thrown
List<String> genders = JsonPath.using(conf2).parse(json).read("$[*]['gender']");
```
JsonPath is shipped with three different JsonProviders:
### JsonProvider SPI
JsonPath is shipped with five different JsonProviders:
* [JsonSmartJsonProvider](https://code.google.com/p/json-smart/) (default)
* [JacksonJsonProvider](https://github.com/FasterXML/jackson)
......@@ -448,8 +493,6 @@ CacheProvider.setCache(new Cache() {
## Sponsored by:
[![JAYWAY](http://www.arctiquator.com/oppenkallkod/assets/images/jayway_logo.png)](http://www.jayway.com/)
[![Analytics](https://ga-beacon.appspot.com/UA-54945131-1/jsonpath/index)](https://github.com/igrigorik/ga-beacon)
[![Analytics](https://ga-beacon.appspot.com/UA-54945131-1/jsonpath/index)](https://github.com/igrigorik/ga-beacon)
......@@ -4,23 +4,29 @@ buildscript {
}
dependencies {
classpath 'me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1'
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3'
classpath 'me.champeau.gradle:japicmp-gradle-plugin:0.1.0'
classpath 'com.github.jengelman.gradle.plugins:shadow:5.1.0'
}
}
ext {
libs = [
slf4jApi: 'org.slf4j:slf4j-api:1.7.16',
jsonSmart: 'net.minidev:json-smart:2.2.1',
jacksonDatabind: 'com.fasterxml.jackson.core:jackson-databind:2.6.3',
gson: 'com.google.code.gson:gson:2.3.1',
gson: 'com.google.code.gson:gson:2.8.5',
hamcrest: 'org.hamcrest:hamcrest:2.1',
jacksonDatabind: 'com.fasterxml.jackson.core:jackson-databind:2.9.8',
jettison: 'org.codehaus.jettison:jettison:1.3.7',
jsonOrg: 'org.json:json:20140107',
tapestryJson: 'org.apache.tapestry:tapestry-json:5.4.0',
hamcrestCore: 'org.hamcrest:hamcrest-core:1.3',
hamcrestLibrary: 'org.hamcrest:hamcrest-library:1.3',
jsonSmart: 'net.minidev:json-smart:2.3',
slf4jApi: 'org.slf4j:slf4j-api:1.7.26',
tapestryJson: 'org.apache.tapestry:tapestry-json:5.4.4',
test: ['org.slf4j:slf4j-simple:1.7.16', 'org.assertj:assertj-core:2.1.0', 'commons-io:commons-io:2.4','org.hamcrest:hamcrest-core:1.3', 'org.hamcrest:hamcrest-library:1.3', 'junit:junit:4.12']
test: [
'commons-io:commons-io:2.4',
'junit:junit:4.12',
'org.assertj:assertj-core:3.11.1',
'org.hamcrest:hamcrest:2.1',
'org.slf4j:slf4j-simple:1.7.26'
]
]
snapshotVersion = false
}
......@@ -30,7 +36,7 @@ allprojects {
ext.buildTimestamp = new Date().format('yyyy-MM-dd HH:mm:ss')
group = 'com.jayway.jsonpath'
version = '2.2.0' + (snapshotVersion ? "-SNAPSHOT" : "")
version = '2.4.0' + (snapshotVersion ? "-SNAPSHOT" : "")
if (JavaVersion.current().isJava8Compatible()) {
tasks.withType(Javadoc) {
......@@ -44,8 +50,8 @@ subprojects {
apply plugin: 'signing'
apply plugin: 'osgi'
sourceCompatibility = 1.6
targetCompatibility = 1.6
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
......@@ -71,8 +77,8 @@ subprojects {
}
}
task wrapper(type: Wrapper) {
gradleVersion = '2.11'
wrapper {
gradleVersion = '5.6.2'
}
//Task used by Heroku for staging
......
......@@ -108,7 +108,6 @@ if (JavaVersion.current().isJava7Compatible()) {
def htmlReportFile = file("${buildDir}/reports/binary-compat-${project.name}.html")
inputs.file file("$configDir/$templateFile")
inputs.file templateFile
outputs.file htmlReportFile
def model = [title : "Binary compatibility report for ${project.name}",
......@@ -131,4 +130,4 @@ if (JavaVersion.current().isJava7Compatible()) {
checkBinaryCompatibility.dependsOn(task)
}
}
}
\ No newline at end of file
}
#Fri Feb 12 10:36:51 CET 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip
#!/usr/bin/env bash
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
......@@ -6,20 +22,38 @@
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
warn () {
echo "$*"
}
die ( ) {
die () {
echo
echo "$*"
echo
......@@ -30,6 +64,7 @@ die ( ) {
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
......@@ -40,26 +75,11 @@ case "`uname`" in
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
......@@ -85,7 +105,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
......@@ -105,8 +125,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
......@@ -150,11 +170,19 @@ if $cygwin ; then
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
......@@ -8,14 +24,14 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
......@@ -49,7 +65,6 @@ goto fail
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
......@@ -60,11 +75,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
......
......@@ -11,7 +11,7 @@ This library is available at the Central Maven Repository. Maven users add this
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-assert</artifactId>
<version>2.1.0</version>
<version>2.2.0</version>
</dependency>
```
......@@ -80,3 +80,46 @@ Use typed matchers for specific JSON representations, if needed
File json = ...
assertThat(json, isJsonFile(withJsonPath("$..author")));
---
### Regarding the use of indefinite paths
When using indefinite path expressions (e.g with wildcards '*'), the result will yield a list. Possibly an _empty_ list if no matching entries were found. If you want to assert that the list will actually contain something, make sure to express this explicitly, e.g checking for the size of the list.
// Given a JSON like this:
{
"items": []
}
// Both of these statements will succeed(!)
assertThat(json, hasJsonPath("$.items[*]"));
assertThat(json, hasJsonPath("$.items[*].name"));
// Make sure to explicitly check for size if you want to catch this scenario as a failure
assertThat(json, hasJsonPath("$.items[*]", hasSize(greaterThan(0))));
// However, checking for the existence of an array works fine, as is
assertThat(json, hasJsonPath("$.not_here[*]"));
---
### Regarding the use of null in JSON
'null' is a valid JSON value. If such a value exist, the path is still considered to be a valid path.
// Given a JSON like this:
{ "none": null }
// All of these will succeed, since '$.none' is a valid path
assertThat(json, hasJsonPath("$.none"));
assertThat(json, isJson(withJsonPath("$.none")));
assertThat(json, hasJsonPath("$.none", nullValue()));
assertThat(json, isJson(withJsonPath("$.none", nullValue())));
// But all of these will fail, since '$.not_there' is not a valid path
assertThat(json, hasJsonPath("$.not_there"));
assertThat(json, isJson(withJsonPath("$.not_there")));
assertThat(json, hasJsonPath("$.not_there", anything()));
assertThat(json, isJson(withJsonPath("$.not_there", anything())));