{"id":41767726,"url":"https://github.com/orangain/json-fuzzy-match","last_synced_at":"2026-01-25T02:37:10.602Z","repository":{"id":45927977,"uuid":"210624142","full_name":"orangain/json-fuzzy-match","owner":"orangain","description":"Custom assertion to check whether a JSON string fuzzily matches a pattern for JVM languages.","archived":false,"fork":false,"pushed_at":"2024-07-21T11:08:58.000Z","size":271,"stargazers_count":11,"open_issues_count":1,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-07-22T03:33:04.688Z","etag":null,"topics":["assertions","assertj","fuzzy-matching","json","junit","matching"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/orangain.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2019-09-24T14:32:16.000Z","updated_at":"2024-07-21T11:07:26.000Z","dependencies_parsed_at":"2024-02-11T10:20:16.378Z","dependency_job_id":"61dea76e-a7c5-4e62-92fe-b554501f4598","html_url":"https://github.com/orangain/json-fuzzy-match","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/orangain/json-fuzzy-match","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orangain%2Fjson-fuzzy-match","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orangain%2Fjson-fuzzy-match/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orangain%2Fjson-fuzzy-match/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orangain%2Fjson-fuzzy-match/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/orangain","download_url":"https://codeload.github.com/orangain/json-fuzzy-match/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orangain%2Fjson-fuzzy-match/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28742548,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T01:40:51.112Z","status":"online","status_checked_at":"2026-01-25T02:00:06.841Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["assertions","assertj","fuzzy-matching","json","junit","matching"],"created_at":"2026-01-25T02:37:09.981Z","updated_at":"2026-01-25T02:37:10.596Z","avatar_url":"https://github.com/orangain.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# json-fuzzy-match [![Maven Central Version](https://img.shields.io/maven-central/v/io.github.orangain/json-fuzzy-match)](https://central.sonatype.com/artifact/io.github.orangain/json-fuzzy-match) [![Java CI](https://github.com/orangain/json-fuzzy-match/workflows/Java%20CI/badge.svg)](https://github.com/orangain/json-fuzzy-match/actions?query=workflow%3A%22Java+CI%22)\n\njson-fuzzy-match provides assertion to check whether a JSON string fuzzily matches a pattern for JVM languages.\nThis is useful when you test JSON response including dynamic or generated value.\n\nFor example, think about testing the following JSON response.\n\n```json5\n{\n    \"id\": \"2c0a9fd7-be2c-4bc2-b134-acc3fa13d400\", // Generated UUID\n    \"title\": \"Example Book\",\n    \"price\": \"9.99\",\n    \"currency\": \"USD\",\n    \"amount\": 10,\n    \"timestamp\": \"2019-09-25T13:34:17Z\" // Dynamic timestamp\n}\n```\n\nInstead of writing:\n\n```kt\nval tree = ObjectMapper().readTree(response.content)\nassertThat(tree.get(\"id\").textValue()).matches(\"[0-9a-z-]+\")\nassertThat(tree.get(\"title\").textValue()).isEqualTo(\"Example Book\")\nassertThat(tree.get(\"price\").textValue()).isEqualTo(\"9.99\")\nassertThat(tree.get(\"currency\").textValue()).isEqualTo(\"USD\")\nassertThat(tree.get(\"amount\").numberValue()).isEqualTo(10)\nassertThat(tree.get(\"timestamp\").isTextual).isTrue()\n```\n\nyou can simply write using json-fuzzy-match:\n\n```kt\n// language=JSON\nJsonStringAssert.assertThat(response.content).jsonMatches(\"\"\"\n    {\n      \"id\": \"#uuid\",\n      \"title\": \"Example Book\",\n      \"price\": \"9.99\",\n      \"currency\": \"USD\",\n      \"amount\": 10,\n      \"timestamp\": \"#datetime\"\n    }\n\"\"\".trimIndent())\n```\n\nIt is recommended to use json-fuzzy-match with languages which have multi-line string literal such as Kotlin, Scala,\nJava 13+ and Groovy.\nSample codes in this README are written in Kotlin.\n\n## Install\n\njson-fuzzy-match is available\non [Maven Central](https://central.sonatype.com/artifact/io.github.orangain/json-fuzzy-match).\n\n### Gradle Kotlin DSL\n\n```kts\ndependencies {\n  testImplementation(\"io.github.orangain:json-fuzzy-match:0.7.0\")\n}\n```\n\n### Maven\n\n```xml\n\u003cdependencies\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003eio.github.orangain\u003c/groupId\u003e\n    \u003cartifactId\u003ejson-fuzzy-match\u003c/artifactId\u003e\n    \u003cversion\u003e0.7.0\u003c/version\u003e\n  \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\n## Usage\n\njson-fuzzy-match provides both [AssertJ](https://joel-costigliola.github.io/assertj/)-style\nand [JUnit](https://junit.org/junit5/)-style assertions.\n\n```kt\n// AssertJ-style\nimport io.github.orangain.jsonmatch.JsonStringAssert\n...\nJsonStringAssert.assertThat(\"\"\"{ \"foo\": \"bar\" }\"\"\").jsonMatches(\"\"\"{ \"foo\": \"#notnull\" }\"\"\")\n```\n\n```kt\n// JUnit-style\nimport io.github.orangain.jsonmatch.JsonMatch.assertJsonMatches\n...\nassertJsonMatches(\"\"\"{ \"foo\": \"bar\" }\"\"\", \"\"\"{ \"foo\": \"#notnull\" }\"\"\")\n```\n\nIn the above examples, the second argument `patternJson` contains `#notnull` marker.\nThe assertion means that value of `foo` field must exist and not null.\nThere are several markers as followings:\n\n| Marker        | Description                                                                                                                                                            |\n|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `#ignore`     | Skip comparison for this field even if the data element or JSON key is present                                                                                         |\n| `#null`       | Expects actual value to be `null`, and the data element or JSON key *must* be present                                                                                  |\n| `#notnull`    | Expects actual value to be not-`null`                                                                                                                                  |\n| `#present`    | Actual value can be any type or *even* `null`, but the key *must* be present                                                                                           |\n| `#notpresent` | Expects the key to be **not** present at all                                                                                                                           |\n| `#array`      | Expects actual value to be a JSON array                                                                                                                                |\n| `#object`     | Expects actual value to be a JSON object                                                                                                                               |\n| `#boolean`    | Expects actual value to be a boolean `true` or `false`                                                                                                                 |\n| `#number`     | Expects actual value to be a number                                                                                                                                    |\n| `#string`     | Expects actual value to be a string                                                                                                                                    |\n| `#uuid`       | Expects actual (string) value to conform to the UUID format                                                                                                            |\n| `#date`       | Expects actual (string) value to conform to the local date in the ISO 8601 extended format                                                                             |\n| `#datetime`   | Expects actual (string) value to conform to the datetime with timezone in the ISO 8601 extended format                                                                 |\n| `#regex STR`  | Expects actual (string) value to match the regular-expression 'STR' (see examples below)                                                                               |\n| `#[NUM] EXPR` | Advanced array marker. When NUM is provided, array must has length just NUM. When EXPR is provided, array's element must match the pattern 'EXPR' (see examples below) |\n\n### Optional marker\n\nYou can use double hash `##` to mark a field as optional. For example, `##string` means that the field can be a string,\nnull or not present.\n\n### Examples\n\n| Pattern                  | `{}`                     | `{ \"a\": null }`          | `{ \"a\": \"abc\" }`         |\n|--------------------------|--------------------------|--------------------------|--------------------------|\n| `{ \"a\": \"#ignore\" }`     | :white_check_mark: match | :white_check_mark: match | :white_check_mark: match |\n| `{ \"a\": \"#null\" }`       | :x: not match            | :white_check_mark: match | :x: not match            |\n| `{ \"a\": \"#notnull\" }`    | :x: not match            | :x: not match            | :white_check_mark: match |\n| `{ \"a\": \"#present\" }`    | :x: not match            | :white_check_mark: match | :white_check_mark: match |\n| `{ \"a\": \"#notpresent\" }` | :white_check_mark: match | :x: not match            | :x: not match            |\n\n#### Date marker\n\n* `{ \"createdOn\": \"2020-07-23\" }` matches the pattern `{ \"createdOn\": \"#date\" }`\n* `{ \"createdOn\": \"2020/07/23\" }` does not match the pattern `{ \"createdOn\": \"#date\" }`\n\n#### Datetime marker\n\n* `{ \"createdAt\": \"2020-07-23T14:56:11+09:00\" }` matches the pattern `{ \"createdAt\": \"#datetime\" }`\n* `{ \"createdAt\": \"2020-07-23T05:56:11Z\" }` matches the pattern `{ \"createdAt\": \"#datetime\" }`\n* `{ \"createdAt\": \"2020-07-23T05:56:11\" }` does not match the pattern `{ \"createdAt\": \"#datetime\" }`\n\n#### Regex marker\n\n* `{ \"id\": \"abc\" }` matches the pattern `{ \"id\": \"#regex [a-z]+\" }`\n* `{ \"id\": \"123\" }` does not match the pattern `{ \"id\": \"#regex [a-z]+\" }`\n\n#### Advanced array marker\n\n* `{ \"tags\": [\"awesome\", \"shop\"] }` matches the following patterns:\n    * `{ \"tags\": \"#[]\" }`\n    * `{ \"tags\": \"#[2]\" }`\n    * `{ \"tags\": \"#[] #string\" }`\n    * `{ \"tags\": \"#[2] #string\" }`\n\n## License\n\nMIT License. See `LICENSE`.\n\n## Acknowledgement\n\nI'm very grateful for the [Karate](https://intuit.github.io/karate/) and its authors.\nThe idea of the marker is heavily inspired by the Karate's wonderful fuzzy matching feature.\nThough json-fuzzy-match does not depend on Karate now, the first version of this library only provided a thin wrapper of\nKarate's feature.\nWithout it, I was not able to develop this library so quickly.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forangain%2Fjson-fuzzy-match","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Forangain%2Fjson-fuzzy-match","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forangain%2Fjson-fuzzy-match/lists"}