Skip to content

Commit

Permalink
Add explicit options for json.dumps() #minor
Browse files Browse the repository at this point in the history
Set explicit options for `json.dumps()`. Biggest change is to match the
separators with ones used in ECMAScript for better overall
interoperability. The character set is also no longer transcoded to
ascii.

The API remains the same, but hashes prior to v0.12.0 will not be
comparable. Added also a notice to README.md to emphasize this aspect.
  • Loading branch information
cobaltine committed Jan 8, 2021
1 parent 7d19196 commit 3ba2697
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ A JSON fingerprint consists of three parts: the version of the underlying canoni

## v1 release checklist (jfpv1)

This is a list of high-level development and documentation tasks, which need to be completed prior to freezing the API for v1. Before v1, backwards-incompatible changes to the API are possible, although not likely since v0.10.0.
This is a list of high-level development and documentation tasks, which need to be completed prior to freezing the API for v1. Before v1, backwards-incompatible changes to the API are possible, although not likely from v0.10.0 onwards. Since the jfpv1 spec is work in progress, the fingerprints may not be fully comparable between different _0.y.z_ versions.

- [ ] Formalized the jfpv1 specification
- [x] JSON type support
Expand Down
10 changes: 9 additions & 1 deletion json_fingerprint/_jfpv1.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@

def _create_json_hash(data: Any, hash_function: str) -> str:
"""Create an sha256 hash from json-converted data, sorted by key names."""
stringified = json.dumps(data, sort_keys=True)
stringified = json.dumps(
data,
allow_nan=False,
ensure_ascii=False,
indent=None,
separators=(',', ':'),
skipkeys=False,
sort_keys=True,
)
if hash_function == 'sha256':
m = hashlib.sha256()
if hash_function == 'sha384':
Expand Down
2 changes: 1 addition & 1 deletion json_fingerprint/tests/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def test_jfpv1_sha256_mixed_order(self):
fp_1 = create(self.test_obj_1, hash_function='sha256', version=1)
fp_2 = create(self.test_obj_2, hash_function='sha256', version=1)
self.assertEqual(fp_1, fp_2)
self.assertEqual(fp_1, 'jfpv1$sha256$0b83bd27ab1227c6da76dc161f4fb4559f1876eb7fb4cc6257e675c8b4175cbd')
self.assertEqual(fp_1, 'jfpv1$sha256$b182c755347a6884fd11f1194cbe0961f548e5ac62be78a56c48c3c05eb56650')

def test_jfpv1_sha256_structural_distinction_1(self):
"""Test jfpv1 json flattener's structural value distinction.
Expand Down
10 changes: 9 additions & 1 deletion json_fingerprint/tests/test_jfpv1.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ def test_create_json_hash(self):
Verify that:
- Key-value pairs are sorted properly and the resulting SHA256 matches the expected hash"""
data = {'value': 'bar', 'path': '{foo}'}
stringified = json.dumps(data, sort_keys=True)
stringified = json.dumps(
data,
allow_nan=False,
ensure_ascii=False,
indent=None,
separators=(',', ':'),
skipkeys=False,
sort_keys=True,
)
m = hashlib.sha256()
m.update(stringified.encode('utf-8'))
expected_hex_digest = m.hexdigest()
Expand Down

0 comments on commit 3ba2697

Please sign in to comment.