Skip to main content

condense-json

PyPI Tests Changelog License

Python function for condensing JSON using replacement strings

Installation

Install this library using pip:

pip install condense-json

Usage

The condense_json function searches a JSON-like object for strings that contain specified replacement substrings. It replaces these substrings with a compact representation, making the JSON more concise. The uncondense_json function reverses this process.

condense_json(obj: JSONInput, replacements: Mapping[str, Optional[str]]) -> Any

  • obj: The JSON value to condense - any nesting of dictionaries, lists, strings, numbers, booleans and None. Top-level lists and strings work too, not just dictionaries.
  • replacements: A mapping where keys are replacement IDs (e.g., "1", "2") and values are the strings they represent. Entries with blank values (None or "") are ignored.

JSONInput is a recursive type alias covering anything representable in JSON, built from covariant container types so that narrowly typed values such as dict[str, str] are accepted without any extra annotation. Results are typed Any, so they can be indexed, iterated and serialized without narrowing.

JSONInput = Union[
    str, int, float, bool, None, "Sequence[JSONInput]", "Mapping[str, JSONInput]"
]

The function returns a modified version of the input obj where matching substrings are replaced. If a string consists entirely of a replacement string, it's replaced with {"$": replacement_id}. If a string contains one or more replacement strings, it's replaced with {"$r": [ ...segments...]} where segments are the parts of the original string and replacement IDs.

Matches are found scanning left to right. Where replacement substrings overlap - for example "quick" and "quick brown fox" - the longest match wins, regardless of the order of the replacements dictionary, so output is deterministic for equivalent inputs.

Example:

from condense_json import condense_json

input_json = {
    "foo": {
        "bar": {
            "string": "This is a string with foxes in it",
            "nested": {
                "more": ["Here is a string", "another with foxes in it too"]
            },
        }
    }
}

replacements = {"1": "with foxes in it"}

condensed_output = condense_json(input_json, replacements)
print(condensed_output)
# Expected output:
# {
#     "foo": {
#         "bar": {
#             "string": {"$r": ["This is a string ", {"$": "1"}]},
#             "nested": {
#                 "more": [
#                     "Here is a string",
#                     {"$r": ["another ", {"$": "1"}, " too"]}
#                 ]
#             }
#         }
#     }
# }

uncondense_json(obj: JSONInput, replacements: Mapping[str, Optional[str]]) -> Any

  • obj: The condensed JSON value.
  • replacements: The same replacements mapping used for condensing.

This function reverses the condense_json operation. It finds the {"$": replacement_id} and {"$r": [ ...segments...]} structures and replaces them with the original strings from the replacements dictionary.

Example:

from condense_json import uncondense_json, condense_json  # Import both

original = {
    "sentence": "The quick brown fox jumps over the lazy dog",
    "nested": {"list": ["fast fox", "lazy dog", "just some text"]},
}
replacements = {"1": "quick brown fox", "2": "lazy dog"}
condensed = condense_json(original, replacements)
uncondensed = uncondense_json(condensed, replacements)
assert uncondensed == original

If the input obj to uncondense_json doesn't contain any condensed structures, it returns the input unchanged.

uncondense_json is strict: it raises condense_json.UncondenseError (a subclass of ValueError) if the condensed input is malformed rather than silently producing corrupted output. This covers markers referencing a replacement ID that is missing from replacements (or one with a blank value, which condense_json never emits markers for), a $r value that is not a list, and $r segments that are not strings or {"$": id} dictionaries.

from condense_json import uncondense_json, UncondenseError

try:
    uncondense_json({"query": {"$": "gt"}}, {"1": "with foxes in it"})
except UncondenseError as ex:
    print(ex)  # Unknown replacement id: 'gt'

Escaping of $, $r and $raw keys

The condensed format gives special meaning to single-key dictionaries with a $ or $r key. If your input data already contains dictionaries of that shape - for example {"price": {"$": "100"}} - they could be misinterpreted when uncondensing.

To prevent this, condense_json escapes any single-key dictionary whose sole key is $, $r or $raw by wrapping it in {"$raw": ...}:

from condense_json import condense_json, uncondense_json

original = {"price": {"$": "100"}}
condensed = condense_json(original, {"1": "with foxes"})
# {'price': {'$raw': {'$': '100'}}}
assert uncondense_json(condensed, {"1": "with foxes"}) == original

uncondense_json removes exactly one $raw wrapper layer and restores the contents without interpreting them as a marker. Because $raw itself is escaped in the same way, this works even if your data already contains $raw keys, and round-trips of condense_json followed by uncondense_json are always lossless - including when applied more than once.

Development

To contribute to this library, checkout the code and run the tests with uv run pytest:

cd condense-json
uv run pytest

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

condense_json-1.0.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

condense_json-1.0-py3-none-any.whl (10.4 kB view details)

Uploaded Python 3

File details

Details for the file condense_json-1.0.tar.gz.

File metadata

  • Download URL: condense_json-1.0.tar.gz
  • Upload date:
  • Size: 11.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for condense_json-1.0.tar.gz
Algorithm Hash digest
SHA256 bcfbd7882d7f66165704a1267e50552316e531fb4bef6eed85d4e6b39e2c47e8
MD5 6c1615526f70565416e49a0215de568c
BLAKE2b-256 c6d3094f137e5f06d2476a97cba540d53b3c7914cd59589bd987ef0147acc1ad

See more details on using hashes here.

Provenance

The following attestation bundles were made for condense_json-1.0.tar.gz:

Publisher: publish.yml on simonw/condense-json

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file condense_json-1.0-py3-none-any.whl.

File metadata

  • Download URL: condense_json-1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for condense_json-1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9f600fb46653b851cf8280a977b2956871dd78f7069763d1c302a093ffe16731
MD5 db6e61b46db21359fdf3d21ff092e25d
BLAKE2b-256 611a1b42a2f046c0244508b52a698e514c1742d96e0799b5dd834285c3ae1739

See more details on using hashes here.

Provenance

The following attestation bundles were made for condense_json-1.0-py3-none-any.whl:

Publisher: publish.yml on simonw/condense-json

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page