在 python 中截断 json 内的长字符串
Truncate long strings inside json in python
给定一些 json
[
{
"default_value": "True",
"feature_name": "feature_1",
"active_on": "remote_1,remote_2,remote_3,remote_4,remote_5,remote_6,remote_7"
},
{
"feature_name": "special_super_duper_feature_wooooooooot",
"active_on": "remote_2"
}
]
如何截断超过 20 个字符的值:
[
{
"default_value": "True",
"feature_name": "feature_1",
"active_on": "remote_1,remote_2..."
},
{
"feature_name": "special_super_dup...",
"active_on": "remote_2"
}
]
尽可能笼统?
编辑:
这是一个更通用的示例:
[
{
"a": {"b": "c"},
"d": "e"
},
{
"a": [{"b": "dugin-walrus-blowing-up-the-view-and-ruining-page-frame"}]
}
]
这里的结局是为任意 json 制作“漂亮的印刷品”。
我想知道是否有仅使用标准库的好方法。
我不知道有任何 built-in 方法可以做到这一点,但一种方法可能是只遍历列表,然后遍历每个字典中的项目,并对每个项目应用一个字符串切片,像这样:
def truncate(d: dict):
for k, v in d.items():
d.update({k: str(v)[:17] + "..."})
return d
json_trunc = list(map(lambda x: truncate(x), json_orig))
如果需要的话,肯定也可以在列表理解中包含截断函数,我只是在这里将它们分开以便于阅读/理解。
您可以通过这种方式使用字符串限制器:
[:17] + '...'
并在您的价值观中循环工作以重新调整其价值观。
示例:
a = 'test text to work with limiter length'
a = a[:17] + '...'
print(a)
结果:
test text to work...
这是我的看法:
import collections
...
def truncate_strings(obj: collections.abc.Iterable, truncate: int, suffix: str = "...") -> int:
"""
@param obj: generic iterable - object to truncate. Implemented for dicts and lists.
Extensible by adding new types to isinstance.
@param truncate: int - total str length to be set. value 0 to disable.
@param suffix: str [Optional] - the truncation string suffix
@returns count: int - number of strings truncated
"""
if not truncate or not obj or isinstance(obj, str):
return 0
count = 0
if isinstance(obj, dict):
for key_ in obj.keys():
if not key_:
return 0
if isinstance(obj.get(key_), str):
if len(obj[key_]) > truncate - len(suffix):
count += 1
obj[key_] = obj[key_][:truncate - len(suffix)] + suffix
else:
count += truncate_strings(key_, truncate, suffix)
elif isinstance(obj, collections.abc.Iterable):
for item in obj:
count += truncate_strings(item, truncate, suffix)
return count
请注意,此函数在可迭代对象上是递归的,因此长列表会杀死您的调用堆栈。应该在合理的大小 jsons 上工作(在 1k 项目 json 数组上测试)
给定一些 json
[
{
"default_value": "True",
"feature_name": "feature_1",
"active_on": "remote_1,remote_2,remote_3,remote_4,remote_5,remote_6,remote_7"
},
{
"feature_name": "special_super_duper_feature_wooooooooot",
"active_on": "remote_2"
}
]
如何截断超过 20 个字符的值:
[
{
"default_value": "True",
"feature_name": "feature_1",
"active_on": "remote_1,remote_2..."
},
{
"feature_name": "special_super_dup...",
"active_on": "remote_2"
}
]
尽可能笼统?
编辑: 这是一个更通用的示例:
[
{
"a": {"b": "c"},
"d": "e"
},
{
"a": [{"b": "dugin-walrus-blowing-up-the-view-and-ruining-page-frame"}]
}
]
这里的结局是为任意 json 制作“漂亮的印刷品”。 我想知道是否有仅使用标准库的好方法。
我不知道有任何 built-in 方法可以做到这一点,但一种方法可能是只遍历列表,然后遍历每个字典中的项目,并对每个项目应用一个字符串切片,像这样:
def truncate(d: dict):
for k, v in d.items():
d.update({k: str(v)[:17] + "..."})
return d
json_trunc = list(map(lambda x: truncate(x), json_orig))
如果需要的话,肯定也可以在列表理解中包含截断函数,我只是在这里将它们分开以便于阅读/理解。
您可以通过这种方式使用字符串限制器:
[:17] + '...'
并在您的价值观中循环工作以重新调整其价值观。
示例:
a = 'test text to work with limiter length'
a = a[:17] + '...'
print(a)
结果:
test text to work...
这是我的看法:
import collections
...
def truncate_strings(obj: collections.abc.Iterable, truncate: int, suffix: str = "...") -> int:
"""
@param obj: generic iterable - object to truncate. Implemented for dicts and lists.
Extensible by adding new types to isinstance.
@param truncate: int - total str length to be set. value 0 to disable.
@param suffix: str [Optional] - the truncation string suffix
@returns count: int - number of strings truncated
"""
if not truncate or not obj or isinstance(obj, str):
return 0
count = 0
if isinstance(obj, dict):
for key_ in obj.keys():
if not key_:
return 0
if isinstance(obj.get(key_), str):
if len(obj[key_]) > truncate - len(suffix):
count += 1
obj[key_] = obj[key_][:truncate - len(suffix)] + suffix
else:
count += truncate_strings(key_, truncate, suffix)
elif isinstance(obj, collections.abc.Iterable):
for item in obj:
count += truncate_strings(item, truncate, suffix)
return count
请注意,此函数在可迭代对象上是递归的,因此长列表会杀死您的调用堆栈。应该在合理的大小 jsons 上工作(在 1k 项目 json 数组上测试)