{"id":23511185,"url":"https://github.com/percolate/jsonmatch","last_synced_at":"2025-04-18T15:03:10.161Z","repository":{"id":5771208,"uuid":"6984733","full_name":"percolate/jsonmatch","owner":"percolate","description":"`jsonmatch` is a small library for diffing Python JSON dictionaries in a flexible, informative way","archived":false,"fork":false,"pushed_at":"2023-03-16T17:46:58.000Z","size":38,"stargazers_count":20,"open_issues_count":1,"forks_count":2,"subscribers_count":73,"default_branch":"master","last_synced_at":"2025-03-29T06:23:16.145Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/percolate.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-12-03T15:43:36.000Z","updated_at":"2025-02-19T14:19:39.000Z","dependencies_parsed_at":"2022-09-17T04:26:16.966Z","dependency_job_id":null,"html_url":"https://github.com/percolate/jsonmatch","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/percolate%2Fjsonmatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/percolate%2Fjsonmatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/percolate%2Fjsonmatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/percolate%2Fjsonmatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/percolate","download_url":"https://codeload.github.com/percolate/jsonmatch/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248699918,"owners_count":21147722,"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":"2024-12-25T12:13:40.215Z","updated_at":"2025-04-18T15:03:10.130Z","avatar_url":"https://github.com/percolate.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"jsonmatch\n=========\n\n[![CircleCI](https://circleci.com/gh/percolate/jsonmatch.svg?style=svg)](https://circleci.com/gh/percolate/jsonmatch)\n\n`jsonmatch` is a small library for matching Python JSON dictionaries against a\nspecification in a flexible, informative way. It was created to make testing\nAPI responses simple, quick, and easy.\n\n```python\n\u003e\u003e\u003e import jsonmatch, re\n\n\u003e\u003e\u003e m = jsonmatch.compile({'a': int, 'b': re.compile(r'\\d+'), 'c': 'c'})\n\n\u003e\u003e\u003e m.matches({'a': 1, 'b': '321', 'c': 'c'})\nTrue\n\n\u003e\u003e\u003e m.matches({'a': 1, 'b': 'not a digit', 'c': 'c'})\nFalse\n\n\u003e\u003e\u003e m.assert_matches({'a': 1, 'b': 'not a digit', 'c': 'c'})\nExpected:\n{'a': \u003ctype 'int'\u003e, 'b': \u003c_sre.SRE_Pattern object at 0x7f70340d5160\u003e, 'c': 'c'}\n\nGot:\n{'a': 1, 'b': 'not a digit', 'c': 'c'}\n\nDiffs:\n{('b',): (RegexpMatch(r'\\d+'), 'not a digit')}\n\n---------------------------------------------------------------------------\nAssertionError                            Traceback (most recent call last)\n...\n\n\u003e\u003e\u003e m.breaks({'a': 1, 'b': 'not a digit', 'c': 'c'}).paths_to_breaks\n{('b',): (RegexpMatch(r'\\d+'), 'not a digit')}\n```\n\n## Installing\n\njsonmatch is on [pypi](https://pypi.python.org/pypi/jsonmatch)\n\n```\npip install jsonmatch\n```\n\n\n## Features\n\n- Flexible matching based on\n    - type\n    - regexp\n    - callable\n    - or plain ol' object.\n- Return unmet expectations in a useful datastructure, not just\n  a string.\n    - `{('path', 'to', 'diff'): (expected_val, actual_val), ...}`\n- Optionally ignore ordering in lists.\n\n\n## Related projects\n\nThere are some other great solutions out there for doing data validation in\nPython, including\n\n- [onctuous](https://pypi.python.org/pypi/onctuous)\n- [voluptuous](https://github.com/alecthomas/voluptuous)\n- [colander](http://docs.pylonsproject.org/projects/colander/en/latest/basics.html#defining-a-colander-schema)\n\nThese libraries are much more robust than jsonmatch, but they're also\nsignificantly more complex.\n\n\n## Example\n\n```python\n\u003e\u003e\u003e import jsonmatch\n\u003e\u003e\u003e import re\n\n\u003e\u003e\u003e matcher = jsonmatch.compile({\n  'a': 123,\n  'b': {\n    'c': re.compile('[abc][ABC]{3}'),  # we can use regexp\n    'd': [1, 2, 3]},\n  'e': lambda x: len(x) == 3,          # and callables\n  'f': list,                           # and also types\n})\n\n# candidates that match the specification yield no breaks\n\u003e\u003e\u003e None == matcher.breaks({\n  'a': 123,\n  'b': {\n    'c': 'aABC',\n    'd': [1, 2, 3],\n  },\n  'e': 'one',\n  'f': [],\n})\n\nTrue\n\n\n# on the other hand, mismatches yield Breaks objects (scalar breakage in 'a')\n\u003e\u003e\u003e print matcher.breaks({\n  'a': 1234,\n  'b': {\n    'c': 'aABC',\n    'd': [1, 2, 3],\n  },\n  'e': 'one',\n  'f': [],\n}).breaks_str\n\n\"\"\"\nExpected:\n{'a': 123,\n 'b': {'c': \u003c_sre.SRE_Pattern object at 0x2c8ed78\u003e, 'd': [1, 2, 3]},\n 'e': \u003cfunction \u003clambda\u003e at 0x2e8c1b8\u003e,\n 'f': []}\n\nGot:\n{'a': 1234, 'b': {'c': 'aABCeee', 'd': [1, 2, 3]}, 'e': 'one', 'f': []}\n\nDiffs:\n{('a',): (123, 1234)}\n\"\"\"\n\n\n# regexp breakage in 'b.c'\n\u003e\u003e\u003e print matcher.breaks({\n  'a': 123,\n  'b': {\n    'c': \"doesn't match\",\n    'd': [1, 2, 3],\n  },\n  'e': 'one',\n  'f': [],\n}).breaks_str\n\n\"\"\"\nExpected:\n{'a': 123,\n 'b': {'c': \u003c_sre.SRE_Pattern object at 0x2c8ed78\u003e, 'd': [1, 2, 3]},\n 'e': \u003cfunction \u003clambda\u003e at 0x2e8c1b8\u003e,\n 'f': []}\n\nGot:\n{'a': 123, 'b': {'c': \"doesn't match\", 'd': [1, 2, 3]}, 'e': 'one', 'f': []}\n\nDiffs:\n{('b', 'c'): (RegexpMatch('[abc][ABC]{3}'), \"doesn't match\")}\n\"\"\"\n```\n\n\n## Python 2/3 compatibility\n\n```python\nfrom __future__ import print_function, unicode_literals\n\n\u003e\u003e\u003e import jsonmatch\n\u003e\u003e\u003e msg = '\\U0001f600'\n\u003e\u003e\u003e print(msg)\n😀\n\n# In PY2, the `str` type will match both unicode and byte string\n\n\u003e\u003e\u003e matcher = jsonmatch.compile({'message': str})\n\u003e\u003e\u003e print(matcher.matches({'message': b'bytestring'}))\nTrue\n\u003e\u003e\u003e print(matcher.matches({'message': msg}))\nTrue\n\n\n# In PY3, `str` will ONLY match unicode string\n\n\u003e\u003e\u003e matcher = jsonmatch.compile({'message': str})\n\u003e\u003e\u003e print(matcher.matches({'message': b'bytestring'}))\nFalse\n\u003e\u003e\u003e print(matcher.matches({'message': msg}))\nTrue\n\n# In order to match byte string, we must compile as `bytes`\n\n\u003e\u003e\u003e matcher = jsonmatch.compile({'message': bytes})\n\u003e\u003e\u003e print(matcher.matches({'message': b'bytestring'}))\nTrue\n\u003e\u003e\u003e print(matcher.matches({'message': msg}))\nFalse\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpercolate%2Fjsonmatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpercolate%2Fjsonmatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpercolate%2Fjsonmatch/lists"}