simonw/condense-json

GitHub: simonw/condense-json

一个通过替换字符串机制压缩和还原 JSON 数据的 Python 库,旨在减少包含重复文本的 JSON 体积。

Stars: 6 | Forks: 3

# condense-json [![PyPI](https://img.shields.io/pypi/v/condense-json.svg)](https://pypi.org/project/condense-json/) [![测试](https://static.pigsec.cn/wp-content/uploads/repos/cas/ce/ce733292a922c08274cf5a2096f8fa4cf01023bfa51a36ef6beecaaef371a9d9.svg)](https://github.com/simonw/condense-json/actions/workflows/test.yml) [![更新日志](https://img.shields.io/github/v/release/simonw/condense-json?include_prereleases&label=changelog)](https://github.com/simonw/condense-json/releases) [![许可证](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/simonw/condense-json/blob/main/LICENSE) 使用替换字符串来压缩 JSON 的 Python 函数 ## 安装 使用 `pip` 安装此库: ``` pip install condense-json ``` ## 用法 `condense_json` 函数会在类似 JSON 的对象中搜索包含指定替换子字符串的字符串。它将这些子字符串替换为紧凑的表示形式,从而使 JSON 更加简洁。`uncondense_json` 函数则会反转此过程。 **`condense_json(obj: JSONInput, replacements: Mapping[str, Optional[str]]) -> Any`** * **`obj`**:要压缩的 JSON 值 - 可以是字典、列表、字符串、数字、布尔值和 `None` 的任意嵌套组合。顶层的列表和字符串同样适用,不仅限于字典。 * **`replacements`**:一个映射,其键是替换 ID(例如 "1"、"2"),值是它们所代表的字符串。值为空(`None` 或 `""`)的条目将被忽略。 `JSONInput` 是一个递归类型别名,涵盖了所有可以用 JSON 表示的内容。它由协变容器类型构建,因此可以接受像 `dict[str, str]` 这样的窄类型值,而无需任何额外的注解。结果类型为 `Any`,因此可以对其进行索引、迭代和序列化,而无需进行类型收窄。 ``` JSONInput = Union[ str, int, float, bool, None, "Sequence[JSONInput]", "Mapping[str, JSONInput]" ] ``` 该函数返回输入 `obj` 的修改版本,其中匹配的子字符串已被替换。如果一个字符串*完全*由一个替换字符串组成,它将被替换为 `{"$": replacement_id}`。如果一个字符串包含一个或多个替换字符串,它将被替换为 `{"$r": [ ...segments...]}`,其中 segments 是原始字符串的部分内容和替换 ID。 匹配是通过从左到右扫描来找到的。当替换子字符串发生重叠时(例如 `"quick"` 和 `"quick brown fox"`),最长的匹配项优先,而不管 `replacements` 字典的顺序如何,因此对于等效的输入,输出是确定性的。 **示例:** ``` 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) # 预期输出: # { # "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`**:已压缩的 JSON 值。 * **`replacements`**:用于压缩的同一个 `replacements` 映射。 该函数会反转 `condense_json` 操作。它会查找 `{"$": replacement_id}` 和 `{"$r": [ ...segments...]}` 结构,并将它们替换为 `replacements` 字典中的原始字符串。 **示例:** ``` 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 ``` 如果输入到 `uncondense_json` 的 `obj` 不包含任何压缩结构,它将原样返回输入。 `uncondense_json` 非常严格:如果压缩后的输入格式不正确,它会抛出 `condense_json.UncondenseError`(`ValueError` 的子类),而不是悄无声息地生成损坏的输出。这涵盖了引用了在 `replacements` 中缺失的替换 ID 的标记(或者引用了值为空的标记,而 `condense_json` 从不为此生成标记),不是列表的 `$r` 值,以及不是字符串或 `{"$": id}` 字典的 `$r` segments。 ``` 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' ``` ### `$`、`$r` 和 `$raw` 键的转义 压缩格式赋予了带有 `$` 或 `$r` 键的单键字典特殊的含义。如果你的输入数据已经包含这种形状的字典(例如 `{"price": {"$": "100"}}`),它们在解压缩时可能会被误解。 为了防止这种情况,`condense_json` 会对所有唯一键为 `$`、`$r` 或 `$raw` 的单键字典进行转义,将其包裹在 `{"$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` 会精确移除一层 `$raw` 包裹,并恢复其内容,且不会将其解释为标记。由于 `$raw` 本身也是以相同方式转义的,所以即使你的数据中已经包含 `$raw` 键,这也能正常工作;此外,先执行 `condense_json` 随后执行 `uncondense_json` 的往返操作始终是无损的——即使在多次应用时也是如此。 ## 开发 要为这个库做贡献,请检出代码并使用 `uv run pytest` 运行测试: ``` cd condense-json uv run pytest ```
标签:JSON, Python, SOC Prime, 压缩优化, 安全规则引擎, 开发工具, 无后门, 逆向工具