给出一些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"}]
}
]
这里的最终目的是制作"pretty-print"对于任意json。我想知道是否有一个很好的方法来做到这一点,只使用标准库。
您可以这样使用字符串限制器:
[:17] + '...'
并在你的值中从循环中重新调整它的值。
的例子:
a = 'test text to work with limiter length'
a = a[:17] + '...'
print(a)
结果:test text to work...
我不知道有什么内置方法可以做到这一点,但一种方法可能是只遍历列表,然后遍历每个字典中的项,并对每个项应用字符串切片,如下所示:
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))
如果需要的话,当然也可以在列表推导式中包含截断函数,我只是为了可读性/可理解性将它们分开了。
我的看法是:
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
注意这个函数在可迭代对象上是递归的,所以长列表会杀死你的调用堆栈。应该工作在合理大小的json虽然(测试在1k项json数组)