diff --git a/json_flatten.py b/json_flatten.py index c8acaa5..6b0acd6 100644 --- a/json_flatten.py +++ b/json_flatten.py @@ -86,7 +86,10 @@ def unflatten(data): current = current[bit] # Now deal with $type suffixes: if _types_re.match(lastkey): - lastkey, lasttype = lastkey.rsplit("$", 2) + # rsplit on "$" once so a key that itself contains "$" (e.g. + # "foo$bar") round-trips intact: "foo$bar$int" -> ("foo$bar", + # "int") rather than crashing on a 3-element unpack. + lastkey, lasttype = lastkey.rsplit("$", 1) value = { "int": int, "float": float, diff --git a/test_json_flatten.py b/test_json_flatten.py index f4efb44..8b248e0 100644 --- a/test_json_flatten.py +++ b/test_json_flatten.py @@ -53,6 +53,15 @@ "foo.[0].phones._$!!$_": "555-555-5555", }, ), + # A key that contains "$" and has a typed value used to crash + # unflatten with `ValueError: too many values to unpack` because the + # type-suffix split was greedy and consumed the whole key. + ("dollar_sign_in_key_with_typed_value", {"foo$bar": 5}, {"foo$bar$int": "5"}), + ( + "multiple_dollar_signs_in_key_with_typed_value", + {"_$home$_": True}, + {"_$home$_$bool": "True"}, + ), ("empty_object", {}, {"$empty": "{}"}), ( "nested_empty_objects",