{"id":25776893,"url":"https://github.com/lukas-krecan/JsonUnit","last_synced_at":"2025-02-27T06:07:00.326Z","repository":{"id":2334410,"uuid":"3296177","full_name":"lukas-krecan/JsonUnit","owner":"lukas-krecan","description":"Compare JSON in your Unit Tests","archived":false,"fork":false,"pushed_at":"2024-10-29T02:21:51.000Z","size":3736,"stargazers_count":887,"open_issues_count":21,"forks_count":114,"subscribers_count":20,"default_branch":"master","last_synced_at":"2024-10-29T15:59:26.787Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lukas-krecan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-01-29T08:33:07.000Z","updated_at":"2024-10-29T14:37:35.000Z","dependencies_parsed_at":"2023-07-05T18:32:05.645Z","dependency_job_id":"73cec58a-1ddb-4d75-81a8-90a72fb85fc9","html_url":"https://github.com/lukas-krecan/JsonUnit","commit_stats":{"total_commits":1407,"total_committers":46,"mean_commits":30.58695652173913,"dds":"0.39232409381663114","last_synced_commit":"3598f5d197e9e828e59cdf0388e9b8006bf37e64"},"previous_names":[],"tags_count":152,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukas-krecan%2FJsonUnit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukas-krecan%2FJsonUnit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukas-krecan%2FJsonUnit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukas-krecan%2FJsonUnit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lukas-krecan","download_url":"https://codeload.github.com/lukas-krecan/JsonUnit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240710836,"owners_count":19845174,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-02-27T06:01:32.832Z","updated_at":"2025-02-27T06:07:00.317Z","avatar_url":"https://github.com/lukas-krecan.png","language":"Java","funding_links":[],"categories":["项目","Testing","测试","Projects","Five Java Libraries to amplify your automated testing"],"sub_categories":["测试","Testing"],"readme":"JsonUnit [![Apache License 2](https://img.shields.io/badge/license-ASF2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0.txt) [![Build Status](https://github.com/lukas-krecan/JsonUnit/workflows/CI/badge.svg)](https://github.com/lukas-krecan/JsonUnit/actions) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.javacrumbs.json-unit/json-unit/badge.svg)](https://maven-badges.herokuapp.com/maven-central/net.javacrumbs.json-unit/json-unit)\n========\n\nJsonUnit is a library that simplifies JSON comparison in tests.\n\n- [APIs](#apis)\n  * [AssertJ integration](#assertj)\n  * [Hamcrest matchers](#hamcrest)\n  * [Spring MVC assertions](#spring)\n  * [Spring WebTestClient](#spring-web-client)\n  * [Spring REST client assertions](#spring-client)\n  * [Kotest assertions](#kotest)\n- [Features](#features)\n  * [JsonPath support](#jsonpath)\n  * [Ignoring values](#ignorevalues)\n  * [Ignoring elements](#ignoreelements)\n  * [Ignoring paths](#ignorepaths)\n  * [Regular expressions](#regexp)\n  * [Type placeholders](#typeplc)\n  * [Custom matchers](#matchers)\n  * [Options](#options)\n  * [Array indexing](#arrayIndexing)\n  * [Numerical comparison](#numbers)\n  * [Escaping dots](#dots)\n  * [Lenient parsing of expected value](#lenient-parsing-of-expected-value)\n  * [DifferenceListener](#differencelistener)\n  * [Jackson Object Mapper customization](#jackson-object-mapper-customization)\n- [Release notes](#release-notes)\n\n\n# \u003ca name=\"apis\"\u003e\u003c/a\u003eAPIs\nThere are several different APIs you can use. They all have more or less the same features, just the usage is\nslightly different.\n\n## \u003ca name=\"assertj\"\u003e\u003c/a\u003eAssertJ integration\nThe recommended API is AssertJ integration which combines the power of JsonUnit and AssertJ.\n\n```java\nimport static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;\nimport static net.javacrumbs.jsonunit.assertj.JsonAssertions.json;\n\n...\n\n// compares two JSON documents (note lenient parsing of expected value)\nassertThatJson(\"{\\\"a\\\":1, \\\"b\\\":2}\").isEqualTo(\"{b:2, a:1}\");\n\n// objects are automatically serialized before comparison\nassertThatJson(jsonObject).isEqualTo(\"{\\n\\\"test\\\": 1\\n}\");\n\n// AssertJ map assertions (numbers are converted to BigDecimals)\nassertThatJson(\"{\\\"a\\\":1}\").isObject().containsEntry(\"a\", BigDecimal.valueOf(1));\n\n// Type placeholders\nassertThatJson(\"{\\\"a\\\":1, \\\"b\\\": {\\\"c\\\" :3}}\")\n    .isObject().containsValue(json(\"{\\\"c\\\" :\\\"${json-unit.any-number}\\\"}\"));\n\n// AssertJ string assertion\nassertThatJson(\"{\\\"a\\\": \\\"value\\\"\")\n    .node(\"a\").isString().isEqualTo(\"value\");\n\n// AssertJ array assertion\nassertThatJson(\"{\\\"a\\\":[{\\\"b\\\": 1}, {\\\"c\\\": 1}, {\\\"d\\\": 1}]}\")\n    .node(\"a\").isArray().contains(json(\"{\\\"c\\\": 1}\"));\n\n// Can ignore array order\nassertThatJson(\"{\\\"a\\\":[{\\\"b\\\": 1}, {\\\"c\\\": 1}, {\\\"d\\\": 1}]}\")\n    .when(Option.IGNORING_ARRAY_ORDER).node(\"a\").isArray()\n    .isEqualTo(json(\"[{\\\"c\\\": 1}, {\\\"b\\\": 1} ,{\\\"d\\\": 1}]\"));\n\n// custom matcher\nassertThatJson(\"{\\\"test\\\":-1}\")\n    .withConfiguration(c -\u003e c.withMatcher(\"positive\", greaterThan(valueOf(0))))\n    .isEqualTo(\"{\\\"test\\\": \\\"${json-unit.matches:positive}\\\"}\");\n\n// and\nassertThatJson(\"{\\\"test\\\":{\\\"a\\\":1, \\\"b\\\":2, \\\"c\\\":3}}\").and(\n    a -\u003e a.node(\"test.a\").isEqualTo(1),\n    a -\u003e a.node(\"test.b\").isEqualTo(2)\n);\n\n// JsonPath support\nassertThatJson(json)\n    .inPath(\"$.store.book\")\n    .isArray()\n    .contains(json(\n        \"            {\\n\" +\n            \"                \\\"category\\\": \\\"reference\\\",\\n\" +\n            \"                \\\"author\\\": \\\"Nigel Rees\\\",\\n\" +\n            \"                \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n            \"                \\\"price\\\": 8.96\\n\" +\n            \"            }\"\n    ));\n```\n\nJsonUnit tries to be clever when parsing the expected value. If the value can be parsed as valid JSON, it's\nparsed so. If it can't be parsed, it's considered to be just a string to be compared. It usually works,\nbut it can lead to unexpected situations, usually with primitive values like numbers and booleans.\n\n```java\n// This test does NOT pass. \"1\" is parsed as JSON containing number 1, the actual value is a string.\nassertThatJson(\"{\\\"id\\\":\\\"1\\\", \\\"children\\\":[{\\\"parentId\\\":\\\"1\\\"}]}\")\n    .inPath(\"children[*].parentId\")\n    .isArray()\n    .containsOnly(\"1\");\n\n// You have to wrap the expected value by `JsonAssertions.value()`\n// to prevent parsing\nassertThatJson(\"{\\\"id\\\":\\\"1\\\", \\\"children\\\":[{\\\"parentId\\\":\\\"1\\\"}]}\")\n    .inPath(\"children[*].parentId\")\n    .isArray()\n    .containsOnly(value(\"1\"));\n\n// \"true\" is valid JSON so it gets parsed to primitive `true`\n// Have to wrap it to JsonAssertions.value() in order to make sure it's not parsed\nassertThatJson(\"{\\\"root\\\":[\\\"true\\\"]}\").node(\"root\").isArray().containsExactly(value(\"true\"));\n```\n\nOn the other hand, if you want to make sure that the expected value is parsed as JSON, use `JsonAssertions.json()`.\n\n### Support for asInstanceOf\nYou can move between vanilla AssertJ and JsonUnit using `asInstanceOf` as in the following example:\n```java\nimport static net.javacrumbs.jsonunit.assertj.JsonAssertions.JSON;\nimport static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;\n\n...\n\nrecord DummyResponse(String trackingId, String json) {}\nDummyResponse resp = new DummyResponse(\"abcd-0001\", \"{ \\\"foo\\\": \\\"bar\\\" }\");\n\nassertThat(resp)\n        .hasFieldOrPropertyWithValue(\"trackingId\", \"abcd-0001\") // \u003c- Assertj API\n        .extracting(\"json\")\n        .asInstanceOf(JSON)\n        .isObject() // \u003c- JsonUnit API\n        .containsEntry(\"foo\", \"bar\");\n```\n\n\n### Kotlin support\nFollowing Kotlin API is supported (notice different import)\n\n```kotlin\n// Kotlin\nimport net.javacrumbs.jsonunit.assertj.assertThatJson\n\nassertThatJson(\"\"\"{\"root\":{\"a\":1, \"b\": 2}}\"\"\") {\n    isObject\n    node(\"root.a\").isEqualTo(1)\n    node(\"root.b\").isEqualTo(2)\n}\n```\n\n\nTo use AssertJ integration, import\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003enet.javacrumbs.json-unit\u003c/groupId\u003e\n    \u003cartifactId\u003ejson-unit-assertj\u003c/artifactId\u003e\n    \u003cversion\u003e4.1.0\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\nFor more examples see [the tests](https://github.com/lukas-krecan/JsonUnit/blob/master/tests/test-base/src/main/java/net/javacrumbs/jsonunit/test/base/AbstractAssertJTest.java).\n\n## \u003ca name=\"hamcrest\"\u003e\u003c/a\u003eHamcrests matchers\nYou use Hamcrest matchers in the following way\n\n```java\nimport static net.javacrumbs.jsonunit.JsonMatchers.*;\nimport static org.junit.Assert.*;\nimport static net.javacrumbs.jsonunit.core.util.ResourceUtils.resource;\n...\n\nassertThat(\"{\\\"test\\\":1}\", jsonEquals(\"{\\\"test\\\": 1}\"));\nassertThat(\"{\\\"test\\\":1}\", jsonPartEquals(\"test\", 1));\nassertThat(\"{\\\"test\\\":[1, 2, 3]}\", jsonPartEquals(\"test[0]\", 1));\n\nassertThat(\"{\\\"test\\\":{\\\"a\\\":1, \\\"b\\\":2, \\\"c\\\":3}}\",\n    jsonEquals(\"{\\\"test\\\":{\\\"b\\\":2}}\").when(IGNORING_EXTRA_FIELDS));\n\n// Can use other Hamcrest matchers too\nassertThat(\"{\\\"test\\\":1}\", jsonPartMatches(\"test\", is(valueOf(1))))\n\nassertThat(\"{\\\"test\\\":1}\", jsonEquals(resource(\"test.json\")));\n```\n\nTo use import\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003enet.javacrumbs.json-unit\u003c/groupId\u003e\n    \u003cartifactId\u003ejson-unit\u003c/artifactId\u003e\n    \u003cversion\u003e4.1.0\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\nFor more examples see [the tests](https://github.com/lukas-krecan/JsonUnit/blob/master/tests/test-base/src/main/java/net/javacrumbs/jsonunit/test/base/AbstractJsonMatchersTest.java).\n\n## \u003ca name=\"spring\"\u003e\u003c/a\u003eSpring MVC assertions\nJsonUnit supports Spring MVC test assertions. For example\n\n```java\nimport static net.javacrumbs.jsonunit.spring.JsonUnitResultMatchers.json;\n...\n\nmockMvc.perform(get(\"/sample\").andExpect(\n    json().isEqualTo(\"{\\\"result\\\":{\\\"string\\\":\\\"stringValue\\\", \\\"array\\\":[1, 2, 3],\\\"decimal\\\":1.00001}}\")\n);\nmockMvc.perform(get(\"/sample\").andExpect(\n    json().node(\"result.string2\").isAbsent()\n);\nmockMvc.perform(get(\"/sample\").andExpect(\n    json().node(\"result.array\").when(Option.IGNORING_ARRAY_ORDER).isEqualTo(new int[]{3, 2, 1})\n);\nmockMvc.perform(get(\"/sample\").andExpect(\n    json().node(\"result.array\").matches(everyItem(lessThanOrEqualTo(valueOf(4))))\n);\n```\n\nFollowing Kotlin DSL is supported:\n\n```kotlin\nmockMvc.get(path).andExpect {\n    jsonContent {\n        node(\"root\").isEqualTo(CORRECT_JSON)\n    }\n}\n```\n\nInside `jsonContent` you have access to all AssertJ API capabilities as described [here](#assertj).\n\nTo use import\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003enet.javacrumbs.json-unit\u003c/groupId\u003e\n    \u003cartifactId\u003ejson-unit-spring\u003c/artifactId\u003e\n    \u003cversion\u003e4.1.0\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\nFor more examples see [the tests](https://github.com/lukas-krecan/JsonUnit/blob/master/json-unit-spring/src/test/java/net/javacrumbs/jsonunit/spring/testit/MockMvcTest.java).\n\n## \u003ca name=\"spring-web-client\"\u003e\u003c/a\u003eSpring WebTestClient\nTo integrate with Spring WebTest client do\n\n```java\nimport static net.javacrumbs.jsonunit.spring.WebTestClientJsonMatcher.json;\n...\n\nclient.get().uri(path).exchange().expectBody().consumeWith(\n    json().isEqualTo(\"{\\\"result\\\":{\\\"string\\\":\\\"stringValue\\\", \\\"array\\\":[1, 2, 3],\\\"decimal\\\":1.00001}}\")\n);\nclient.get().uri(path).exchange().expectBody().consumeWith(\n    json().node(\"result.string2\").isAbsent()\n);\nclient.get().uri(path).exchange().expectBody().consumeWith(\n    json().node(\"result.array\").when(Option.IGNORING_ARRAY_ORDER).isEqualTo(new int[]{3, 2, 1})\n);\nclient.get().uri(path).exchange().expectBody().consumeWith(\n    json().node(\"result.array\").matches(everyItem(lessThanOrEqualTo(valueOf(4))))\n);\n```\n\nFor Kotlin, you can use our bespoke DSL\n\n```kotlin\nimport net.javacrumbs.jsonunit.spring.jsonContent\n...\nclient.get().uri(path).exchange().expectBody()\n    .jsonContent {\n        isEqualTo(CORRECT_JSON)\n    }\n```\n\nImport\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003enet.javacrumbs.json-unit\u003c/groupId\u003e\n    \u003cartifactId\u003ejson-unit-spring\u003c/artifactId\u003e\n    \u003cversion\u003e4.1.0\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\nFor more examples see [the tests](https://github.com/lukas-krecan/JsonUnit/blob/master/json-unit-spring/src/test/java/net/javacrumbs/jsonunit/spring/testit/WebTestClientTest.java).\n\n## \u003ca name=\"spring-mockmvc-assertj\"\u003e\u003c/a\u003eSpring AssertJ for MockMvc\nSince version 4.0.0 JsonUnit supports Spring MockMvc AssertJ assertions.\nYou can use it like this:\n\n```java\nimport static net.javacrumbs.jsonunit.assertj.JsonAssertions.jsonUnitJson;\n\n...\n\nassertThat(mvc.get().uri(\"/sample\"))\n    .hasStatusOk()\n    .bodyJson()\n    .convertTo(jsonUnitJson()) // Switch to JsonUnit assert\n    .inPath(\"result.array\") // This is JsonUnit\n    .isArray()\n    .containsExactly(1, 2, 3);\n```\n\n## \u003ca name=\"spring-client\"\u003e\u003c/a\u003eSpring REST client assertions\n\n```java\nimport static net.javacrumbs.jsonunit.spring.JsonUnitRequestMatchers.json;\n...\nmockServer.expect(requestTo(URI))\n      .andExpect(json().isEqualTo(json))\n      .andRespond(withSuccess(jsonResponse, MediaType.APPLICATION_JSON_UTF8));\n```\n\nTo use import\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003enet.javacrumbs.json-unit\u003c/groupId\u003e\n    \u003cartifactId\u003ejson-unit-spring\u003c/artifactId\u003e\n    \u003cversion\u003e4.1.0\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\nFor more examples see [the tests](https://github.com/lukas-krecan/JsonUnit/blob/master/json-unit-spring/src/test/java/net/javacrumbs/jsonunit/spring/testit/ClientTest.java).\n\n## \u003ca name=\"kotest\"\u003e\u003c/a\u003eKotest assertions\nJsonUnit supports [Kotest assertions](https://kotest.io/docs/assertions/assertions.html).\n\nImport:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003enet.javacrumbs.json-unit\u003c/groupId\u003e\n    \u003cartifactId\u003ejson-unit-kotest\u003c/artifactId\u003e\n    \u003cversion\u003e4.1.0\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\nAnd enjoy:\n\n```kotlin\n\"\"\"{\"test\":1}\"\"\" should equalJson(\"\"\"{\"test\": 1}\"\"\")\n\n// Provide configuration\n\"\"\"{\"test\":1.01}\"\"\" should equalJson(\"\"\"{\"test\":1}\"\"\", configuration { withTolerance(0.1) })\n\n// Use inPath\n\"\"\"{\"test\":1}\"\"\" inPath \"test\" should equalJson(\"1\")\n\n// Clues with nesting\n\"\"\"{\"test\": {\"nested\": 1}}\"\"\".inPath(\"test\").asClue {\n    it inPath \"nested\" should equalJson(\"2\")\n}\n\n\"\"\"{\"test\":1}\"\"\".inPath(\"test\").shouldBeJsonNumber()\n    // shouldBeJsonNumber returns BigDecimal, so we can use standard kotest assertions\n    // PLease note that numbers are converted to BigDecimals\n    .shouldBeEqualComparingTo(valueOf(1))\n\n// The same for arrays generated by JsonPath\n\"\"\"{\"test\": [{\"a\": \"a\"}, {\"a\": true}, {\"a\": null}, {\"a\": 4}]}\"\"\".inPath(\"$.test[*].a\")\n    .shouldBeJsonArray()\n    .shouldContainExactly(\"a\", true, null, valueOf(4))\n\n// ... and objects\n\"\"\"{\"a\":1, \"b\": true}\"\"\".shouldBeJsonObject().shouldMatchAll(\n    \"a\" to { it should beJsonNumber() },\n    \"b\" to { it should beJsonBoolean() }\n)\n```\n\nSee the [tests](https://github.com/lukas-krecan/JsonUnit/blob/master/json-unit-kotest/src/test/kotlin/net/javacrumbs/jsonunit/kotest/test/KotestTest.kt) for more examples.\n\n# Features\nJsonUnit support all this features regardless of API you use.\n\n## \u003ca name=\"jsonpath\"\u003e\u003c/a\u003eJsonPath support\nYou can use JsonPath navigation together with JsonUnit. It has native support in AssertJ and Spring integration, so you can do something like this:\n\n```java\n// AssertJ style\nassertThatJson(json)\n    .inPath(\"$.store.book\")\n    .isArray()\n    .contains(json(\n        \"            {\\n\" +\n            \"                \\\"category\\\": \\\"reference\\\",\\n\" +\n            \"                \\\"author\\\": \\\"Nigel Rees\\\",\\n\" +\n            \"                \\\"title\\\": \\\"Sayings of the Century\\\",\\n\" +\n            \"                \\\"price\\\": 8.96\\n\" +\n            \"            }\"\n    ));\n```\n\n## \u003ca name=\"ignorevalues\"\u003e\u003c/a\u003eIgnoring values\nSometimes you need to ignore certain values when comparing. It is possible to use `${json-unit.ignore}` or `#{json-unit.ignore}`\nplaceholder like this\n\n```java\n// AssertJ API\nassertThatJson(\"{\\\"a\\\":1}\")\n    .isEqualTo(json(\"{\\\"a\\\":\\\"${json-unit.ignore}\\\"}\"));\n```\nPlease note that the assertion will fail if the `test` element is missing in the actual value.\n\n## \u003ca name=\"ignoreelements\"\u003e\u003c/a\u003eIgnoring elements\nIf the element needs to be ignored completely you can use `${json-unit.ignore-element}`\nplaceholder.\n\n```java\n// AssertJ API\nassertThatJson(\"{\\\"root\\\":{\\\"test\\\":1, \\\"ignored\\\": null}}\")\n      .isEqualTo(\"{\\\"root\\\":{\\\"test\\\":1, \\\"ignored\\\": \\\"${json-unit.ignore-element}\\\"}}\");\n```\n\nThe assertion will not fail if the element is missing in the actual value.\n\n## \u003ca name=\"ignorepaths\"\u003e\u003c/a\u003eIgnoring paths\n\n`whenIgnoringPaths` configuration option makes JsonUnit ignore the specified paths in the actual value. If the path\nmatches, it's completely ignored. It may be missing, null or have any value. Also `when(paths(...), thenIgnore()` can be used.\n\n```java\n// AssertJ style\nassertThatJson(\"{\\\"root\\\":{\\\"test\\\":1, \\\"ignored\\\": 1}}\")\n    .whenIgnoringPaths(\"root.ignored\"))\n    .isEqualTo(\"{\\\"root\\\":{\\\"test\\\":1}}\");\n\n// Hamcrest matcher\nassertThat(\n  \"{\\\"root\\\":{\\\"test\\\":1, \\\"ignored\\\": 2}}\",\n  jsonEquals(\"{\\\"root\\\":{\\\"test\\\":1, \\\"ignored\\\": 1}}\").whenIgnoringPaths(\"root.ignored\")\n);\n```\n\nArray index placeholder\n```java\nassertThatJson(\"[{\\\"a\\\":1, \\\"b\\\":2},{\\\"a\\\":1, \\\"b\\\":3}]\")\n    .whenIgnoringPaths(\"[*].b\")\n    .isEqualTo(\"[{\\\"a\\\":1, \\\"b\\\":0},{\\\"a\\\":1, \\\"b\\\":0}]\");\n```\nPlease note that if you use JsonPath, you should start the path to be ignored by `$`\nAlso note that `whenIgnoringPaths` method supports full JsonPath syntax only in AssertJ API, all the other flavors support only\nexact path or array index placeholder as described above.\n\nJsonPath with whenIgnoringPaths example:\n```java\n// AssertJ API\nassertThatJson(\"{\\\"fields\\\":[\" +\n        \"{\\\"key\\\":1, \\\"name\\\":\\\"AA\\\"},\" +\n        \"{\\\"key\\\":2, \\\"name\\\":\\\"AB\\\"},\" +\n        \"{\\\"key\\\":3, \\\"name\\\":\\\"AC\\\"}\" +\n    \"]}\")\n    .whenIgnoringPaths(\"$.fields[?(@.name=='AA')].key\")\n    .isEqualTo(\"{\\\"fields\\\":[\" +\n        \"{\\\"key\\\":2, \\\"name\\\":\\\"AA\\\"},\" +\n        \"{\\\"key\\\":2, \\\"name\\\":\\\"AB\\\"},\" +\n        \"{\\\"key\\\":3, \\\"name\\\":\\\"AC\\\"}\" +\n    \"]}\");\n```\n\n\n## \u003ca name=\"regexp\"\u003e\u003c/a\u003eRegular expressions\nIt is also possible to use regular expressions to compare string values\n\n```java\nassertThatJson(\"{\\\"test\\\": \\\"ABCD\\\"}\")\n    .isEqualTo(\"{\\\"test\\\": \\\"${json-unit.regex}[A-Z]+\\\"}\");\n```\n\n\nFor matching just part of the string, you can use this (we have to escape twice, once for Java, once for JSON)\n```java\nassertThatJson(\"{\\\"test\\\": \\\"This is some text followed by: ABCD, followed by this\\\"}\")\n            .isEqualTo(\"{\\\"test\\\": \\\"${json-unit.regex}^\\\\\\\\QThis is some text followed by: \\\\\\\\E[A-Z]+\\\\\\\\Q, followed by this\\\\\\\\E$\\\"}\");\n```\n\nSince this is quite hard to write, you can implement an expression builder like\n[this](https://github.com/lukas-krecan/JsonUnit/commit/75d68ef1852ade004e93ca42d676f4b996631974#diff-642a52fede8473f98c5a7b25f34c6bd68f33160cf22733127f7f7f13f3cb2fc6R713).\n\n\n## \u003ca name=\"typeplc\"\u003e\u003c/a\u003eType placeholders\nIf you want to assert just a type, but you do not care about the exact value, you can use any-* placeholder like this\n\n```java\nassertThatJson(\"{\\\"test\\\":\\\"value\\\"}\")\n    .isEqualTo(\"{test:'${json-unit.any-string}'}\");\n\nassertThatJson(\"{\\\"test\\\":true}\")\n    .isEqualTo(\"{\\\"test\\\":\\\"${json-unit.any-boolean}\\\"}\");\n\nassertThatJson(\"{\\\"test\\\":1.1}\")\n    .isEqualTo(\"{\\\"test\\\":\\\"${json-unit.any-number}\\\"}\");\n\n```\n\nYou can also use hash instead of string `#{json-unit.any-string}` for example if you are using language with string interpolation\nlike Kotlin.\n\n## \u003ca name=\"matchers\"\u003e\u003c/a\u003eCustom matchers\nIn some special cases you might want to use your own matcher in the expected document.\n```java\n assertThatJson(\"{\\\"test\\\":-1}\")\n             .withMatcher(\"positive\", greaterThan(valueOf(0)))\n             .isEqualTo(\"{\\\"test\\\": \\\"${json-unit.matches:positive}\\\"}\");\n```\n\nIn even more special cases, you might want to parametrize your matcher.\n```java\n Matcher\u003c?\u003e divisionMatcher = new DivisionMatcher();\n assertThatJson(\"{\\\"test\\\":5}\")\n    .withMatcher(\"isDivisibleBy\", divisionMatcher)\n    .isEqualTo(\"{\\\"test\\\": \\\"${json-unit.matches:isDivisibleBy}3\\\"}\");\n\n private static class DivisionMatcher extends BaseMatcher\u003cObject\u003e implements ParametrizedMatcher {\n     private BigDecimal param;\n\n     public boolean matches(Object item) {\n         return ((BigDecimal)item).remainder(param).compareTo(ZERO) == 0;\n     }\n\n     public void describeTo(Description description) {\n         description.appendValue(param);\n     }\n\n     @Override\n     public void describeMismatch(Object item, Description description) {\n         description.appendText(\"It is not divisible by \").appendValue(param);\n     }\n\n     public void setParameter(String parameter) {\n         this.param = new BigDecimal(parameter);\n     }\n }\n```\nIf you need a matcher with more than one parameter, you can implement it\nlike [this](https://stackoverflow.com/a/66183629/277042).\n\n## \u003ca name=\"options\"\u003e\u003c/a\u003eOptions\n\nThere are multiple options how you can configure the comparison\n\n**TREATING_NULL_AS_ABSENT** - fields with null values are equivalent to absent fields. For example, this test passes\n\n```java\nassertThatJson(\"{\\\"test\\\":{\\\"a\\\":1, \\\"b\\\": null}}\")\n    .when(TREATING_NULL_AS_ABSENT)\n    .isEqualTo(\"{\\\"test\\\":{\\\"a\\\":1}}\");\n```\n\n**IGNORING_ARRAY_ORDER** - ignores order in arrays\n\n```java\nassertThatJson(\"{\\\"test\\\":[1,2,3]}\")\n    .when(IGNORING_ARRAY_ORDER)\n    .isEqualTo(\"{\\\"test\\\":[3,2,1]}\");\n```\n\n**IGNORING_EXTRA_ARRAY_ITEMS** - ignores unexpected array items\n```java\nassertThatJson(\"{\\\"test\\\":[1,2,3,4]}\")\n    .when(IGNORING_EXTRA_ARRAY_ITEMS)\n    .isEqualTo(\"{\\\"test\\\":[1,2,3]}\");\n\n\nassertThatJson(\"{\\\"test\\\":[5,5,4,4,3,3,2,2,1,1]}\")\n    .when(IGNORING_EXTRA_ARRAY_ITEMS, IGNORING_ARRAY_ORDER)\n    .isEqualTo(\"{\\\"test\\\":[1,2,3]}\");\n```\n\n**IGNORING_EXTRA_FIELDS** - ignores extra fields in the compared value\n\n```java\nassertThatJson(\"{\\\"test\\\":{\\\"a\\\":1, \\\"b\\\":2, \\\"c\\\":3}}\")\n    .when(IGNORING_EXTRA_FIELDS)\n    .isEqualTo(\"{\\\"test\\\":{\\\"b\\\":2}}\");\n```\n\n**IGNORE_VALUES** - ignores values and compares only types\n\n```java\nassertThatJson(\"{\\\"a\\\":2,\\\"b\\\":\\\"string2\\\"}\")\n    .when(paths(\"a\", \"b\"), then(IGNORING_VALUES))\n    .isEqualTo(\"{\\\"a\\\":1,\\\"b\\\":\\\"string\\\"}\");\n```\n\n**FAIL_FAST** - stops comparison at the first difference. May provide performance benefits for large JSONs and use-cases that\ndo not require to know all the differences.\n\nIt is possible to combine options.\n\n```java\nassertThatJson(\"{\\\"test\\\":[{\\\"key\\\":3},{\\\"key\\\":2, \\\"extraField\\\":2},{\\\"key\\\":1}]}\")\n    .when(IGNORING_EXTRA_FIELDS, IGNORING_ARRAY_ORDER)\n    .isEqualTo(\"{\\\"test\\\":[{\\\"key\\\":1},{\\\"key\\\":2},{\\\"key\\\":3}]}\");\n```\n\n**REPORTING_DIFFERENCE_AS_NORMALIZED_STRING** - reports errors as normalized strings. Applies some basic normalization\nto compared values and then reports full json strings, so you can see the difference in the IDE diff.\n\n\nIn Hamcrest assertion you can set the option like this\n\n```java\nassertThat(\"{\\\"test\\\":{\\\"a\\\":1, \\\"b\\\":2, \\\"c\\\":3}}\",\n    jsonEquals(\"{\\\"test\\\":{\\\"b\\\":2}}\").when(IGNORING_EXTRA_FIELDS));\n```\n\nYou can define options locally (for specific paths) by using `when(path(...), then(...))`:\n```java\n// ignore array order for [*].a\n// AssertJ\nassertThatJson(\"{\\\"test\\\":{\\\"a\\\":1,\\\"b\\\":2,\\\"c\\\":3}}\").when(paths(\"test.c\"), then(IGNORING_VALUES))\n    .isEqualTo(\"{\\\"test\\\":{\\\"a\\\":1,\\\"b\\\":2,\\\"c\\\":4}}\");\n// ignore array order everywhere but [*].b\nassertThatJson(\"[{\\\"b\\\":[4,5,6]},{\\\"b\\\":[1,2,3]}]\")\n    .when(IGNORING_ARRAY_ORDER)\n    .when(path(\"[*].b\"), thenNot(IGNORING_ARRAY_ORDER))\n    .isEqualTo(\"[{\\\"b\\\":[1,2,3]},{\\\"b\\\":[4,5,6]}]\");\n// ignore extra fields in the object \"a\"\nassertThatJson(\"{\\\"a\\\":{\\\"a1\\\":1,\\\"a2\\\":2},\\\"b\\\":{\\\"b1\\\":1,\\\"b2\\\":2}}\")\n    .when(path(\"a\"), then(IGNORING_EXTRA_FIELDS))\n    .isEqualTo(\"{\\\"a\\\":{\\\"a1\\\":1},\\\"b\\\":{\\\"b1\\\":1}}\"))\n// ignore extra array items in the array\nassertThatJson(\"{\\\"a\\\":[1,2,3]}\")\n    .when(path(\"a\"), then(IGNORING_EXTRA_ARRAY_ITEMS))\n    .isEqualTo(\"{\\\"a\\\":[1,2]}\");\n// Hamcrest\nassertThat(\"{\\\"test\\\":{\\\"a\\\":1,\\\"b\\\":2,\\\"c\\\":3}}\",\n    jsonEquals(\"{\\\"test\\\":{\\\"a\\\":1,\\\"b\\\":2,\\\"c\\\":4}}\").when(path(\"test.c\"), then(IGNORING_VALUES)));\n\n```\nNote that **TREATING_NULL_AS_ABSENT** and **IGNORING_VALUES** require exact paths to ignored fields:\n```java\n// ignoring number and str\nassertThatJson(\"{\\\"a\\\":2,\\\"b\\\":\\\"string2\\\"}\")\n    .when(paths(\"a\", \"b\"), then(IGNORING_VALUES))\n    .isEqualTo(\"{\\\"a\\\":1,\\\"b\\\":\\\"string\\\"}\");\n// treat null B as absent B\nassertThatJson(\"{\\\"A\\\":1,\\\"B\\\":null}\")\n    .when(path(\"B\"), then(TREATING_NULL_AS_ABSENT))\n    .isEqualTo(\"{\\\"A\\\":1}\");\n```\nAll other options require paths to objects or arrays where values or order should be ignored.\n\n## \u003ca name=\"arrayIndexing\"\u003e\u003c/a\u003eArray indexing\nYou can use negative numbers to index arrays form the end\n```java\nassertThatJson(\"{\\\"root\\\":{\\\"test\\\":[1,2,3]}}\")\n    .node(\"root.test[-1]\").isEqualTo(3);\n```\n\n## \u003ca name=\"numbers\"\u003e\u003c/a\u003eNumerical comparison\nNumbers are by default compared in the following way:\n\n* If the type differs, the number is different. So 1 and 1.0 are different (int vs. float). This does not apply when Moshi is used since it [parses all numbers as Doubles](https://github.com/square/moshi/issues/192).\n* Floating number comparison is exact, down to the scale - 1.0 and 1.00 are considered to be different.\n\nYou can change this behavior by setting tolerance. If you set tolerance to `0` two numbers are considered equal if they are\nequal mathematically even though they have different type or precision (`a.compareTo(b) == 0`).\n\n```java\nassertThatJson(\"{\\\"test\\\":1.00}\").node(\"test\").withTolerance(0).isEqualTo(1);\n```\n\nIf you set tolerance to non-zero value, the values are considered equal if `abs(a-b) \u003c= tolerance`.\n```java\nassertThatJson(\"{\\\"test\\\":1.00001}\").node(\"test\").withTolerance(0.001).isEqualTo(1);\n```\n\nOr you can use Hamcrest matcher\n\n```java\nimport static java.math.BigDecimal.valueOf;\n...\nassertThatJson(\"{\\\"test\\\":1.10001}\").node(\"test\")\n    .matches(closeTo(valueOf(1.1), valueOf(0.001)));\n```\n\nIf you are interested why 1 and 1.0 are treated as different numbers please read this [comment](https://github.com/lukas-krecan/JsonUnit/issues/229#issuecomment-623882801).\n\nIf you want to have special handling of numerical values, you can inject your own number comparator.\n\n```java\nassertThatJson(\"{\\\"a\\\":1.0}\")\n    .withConfiguration(c -\u003e c.withNumberComparator(numberComparator))\n    .isEqualTo(\"{\\\"a\\\":1.00}\");\n```\n\n## \u003ca name=\"dots\"\u003e\u003c/a\u003eEscaping dots\nSometimes you have dots in JSON element names, and you need to address those elements. It is possible to escape dots like this\n\n```java\nassertThatJson(\"{\\\"name.with.dot\\\": \\\"value\\\"}\").node(\"name\\\\.with\\\\.dot\").isStringEqualTo(\"value\");\n```\n\n## \u003ca name=\"lenient\"\u003e\u003c/a\u003eLenient parsing of expected value\nWriting JSON string in Java is huge pain. JsonUnit parses expected values leniently, so you do not have to quote keys,\nand you can use single quotes instead of double quotes. Please note that the actual value being compared is parsed in strict mode.\n\n```java\nassertThatJson(\"{\\\"a\\\":\\\"1\\\", \\\"b\\\":2}\").isEqualTo(\"{b:2, a:'1'}\");\n```\n\n## \u003ca name=\"object-mapper-cust\"\u003e\u003c/a\u003eJackson Object Mapper customization\nIf you need to customize Jackson 2 Object Mapper, you can do using [SPI](https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html).\nImplement `net.javacrumbs.jsonunit.providers.Jackson2ObjectMapperProvider`.\n\n```java\npublic class Java8ObjectMapperProvider implements Jackson2ObjectMapperProvider {\n    private final ObjectMapper mapper;\n\n    private final ObjectMapper lenientMapper;\n\n\n    public Java8ObjectMapperProvider() {\n        mapper = new ObjectMapper().registerModule(new JavaTimeModule());\n        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);\n\n        lenientMapper = new ObjectMapper().registerModule(new JavaTimeModule());\n        lenientMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);\n        lenientMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);\n        lenientMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);\n    }\n\n    @Override\n    public ObjectMapper getObjectMapper(boolean lenient) {\n        return lenient ? lenientMapper : mapper;\n    }\n}\n```\n\nand register it in `META-INF/services/net.javacrumbs.jsonunit.providers.Jackson2ObjectMapperProvider`.\nSee [this example](https://github.com/lukas-krecan/JsonUnit/commit/8dc7c884448c7373886dcf3b0eabfecf47c0710b).\n\n## Logging\n\nAlthough the differences are printed out by the assert statement, sometimes you use JsonUnit with other libraries like\n[Jadler](https://github.com/jadler-mocking/jadler) that do not print the differences between documents. In such case, you can switch on the\nlogging. JsonUnit uses [SLF4J](http://www.slf4j.org/). The only thing you need to do is to configure your logging\nframework to log `net.javacrumbs.jsonunit.difference` on DEBUG level.\n\n## DifferenceListener\n\nIf you need better difference reporting, you can implement [`DifferenceListener`](https://github.com/lukas-krecan/JsonUnit/blob/master/json-unit-core/src/main/java/net/javacrumbs/jsonunit/core/listener/DifferenceListener.java) and use it this way\n\n```java\nassertThatJson(\"{\\\"test\\\":-1}\")\n    .withDifferenceListener(listener)\n    .isEqualTo(json);\n```\n\n## Selecting underlying library\n\nJsonUnit is trying to cleverly match which JSON library to use. In case you need to change the default behavior, you can\nuse `json-unit.libraries` system property. For example `-Djson-unit.libraries=jackson2,gson`\nor `System.setProperty(\"json-unit.libraries\", \"jackson2\");`. Supported values are gson, json.org, moshi, jackson2\n\nLicence\n-------\nJsonUnit is licensed under [Apache 2.0 licence](https://www.apache.org/licenses/LICENSE-2.0).\n\nRelease notes\n=============\nReleased notes moved to a [separate file](RELEASES.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukas-krecan%2FJsonUnit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flukas-krecan%2FJsonUnit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukas-krecan%2FJsonUnit/lists"}