Skip to content

Instantly share code, notes, and snippets.

@kalda341
Created August 18, 2019 05:25
Show Gist options
  • Save kalda341/d215664dfc27a0ba21ee896643df8a20 to your computer and use it in GitHub Desktop.
Save kalda341/d215664dfc27a0ba21ee896643df8a20 to your computer and use it in GitHub Desktop.
def canonical_jsonify(json_node):
# Escape character | quote | backslash | high surrogate not followed by low, or low surrogate not following
# a high surrogate
replace_regex = r'[\u0000-\u001F]|\"|\\|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]'
to_slash_escape = {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'\"': '\\\"',
'\\': '\\\\',
}
def escape_match(match):
character = match.group()
# Use slash escape if possible, otherwise use unicode escape
if character in to_slash_escape:
return to_slash_escape[character]
else:
return '\\u{0:04X}'.format(ord(character))
def do_encode(json_node, depth):
if depth > 100:
raise ValueError('Max depth exceeded. Structure is probably recursive.')
if json_node is None:
return 'null'
elif isinstance(json_node, bool):
return 'true' if json_node else 'false'
elif isinstance(json_node, int):
return str(json_node)
elif isinstance(json_node, float):
exponent = int(math.log10(abs(json_node)))
mantissa = json_node / (10 ** exponent)
return '{}E{}'.format(mantissa, exponent)
elif isinstance(json_node, str):
return '"{}"'.format(re.sub(replace_regex, escape_match, json_node))
elif isinstance(json_node, dict):
sorted_kv_pairs = sorted(json_node.items(), key=lambda pair: pair[0])
node_contents = ','.join([
':'.join([do_encode(x, depth + 1) for x in [k, v]])
for k, v in sorted_kv_pairs
])
return '{{{}}}'.format(node_contents)
elif isinstance(json_node, list):
node_contents = ','.join([do_encode(x, depth + 1) for x in json_node])
return '[{}]'.format(node_contents)
else:
raise ValueError('Unknown type: '.format(type(json_node)))
return do_encode(json_node, 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment