Python中的json.loads和json.load方法截断嵌套json对象的问题及其解决方案

152 阅读2分钟

在python中使用json.loads或json.load方法将json字符串转换为python对象时,可能会遇到嵌套json对象被截断的问题。以下是一个示例代码:

import json

foo = '{"root":"cfb-score","children":{"gamecode":{"attribute":"global-id"},"gamestate":{"attribute":"status-id","attribute":"status","attribute":"quarter","attribute":"minutes","attribute":"seconds","attribute":"team-possession-id","attribute":"yards-from-goal","attribute":"down","attribute":"distance","attribute":"segment-number","attribute":"active-state"},"gametype":{"attribute":"type","attribute":"detail"},"stadium":{"attribute":"name","attribute":"city","attribute":"state"},"visiting-team:team-name":{"attribute":"alias"},"visiting-team:team-code":{"attribute":"global-id"},"visiting-team:team-rank":{"attribute":"rank"}}}'

bar = json.loads(foo)
print(json.dumps(bar))

当运行这段代码时,会发现所有最低级别的“children”都被截断或覆盖,除了最后一个。

  1. 解决方案

  2. 使用json.load方法时,确保json字符串中的键都是唯一的

    JSON对象可以转换为python字典,这意味着json字符串中的键不能重复。如果有多个键具有相同的值,则只会保留最后一个键。

  3. 在json字符串中使用数组存储具有相同值的键

    如果您需要在json字符串中存储具有相同值的键,则可以使用数组来存储这些键。例如,以下json字符串使用数组存储了“gamestate”下的属性:

{"root":"cfb-score","children":{"gamecode":{"attribute":"global-id"},"gamestate":{"attributes":["status-id","status","quarter","minutes","seconds","team-possession-id","yards-from-goal","down","distance","segment-number","active-state"]},"gametype":{"attribute":"type","attribute":"detail"},"stadium":{"attribute":"name","attribute":"city","attribute":"state"},"visiting-team:team-name":{"attribute":"alias"},"visiting-team:team-code":{"attribute":"global-id"},"visiting-team:team-rank":{"attribute":"rank"}}}
  1. 使用第三方json解析库,如ujson或simplejson

    这些库可能会更好地处理嵌套json对象,并且可能不会出现截断问题。

以下是一些代码示例,演示了解决方案2和3:

# 解决方案2:使用数组存储具有相同值的键

foo = '{"root":"cfb-score","children":{"gamecode":{"attribute":"global-id"},"gamestate":{"attributes":["status-id","status","quarter","minutes","seconds","team-possession-id","yards-from-goal","down","distance","segment-number","active-state"]},"gametype":{"attribute":"type","attribute":"detail"},"stadium":{"attribute":"name","attribute":"city","attribute":"state"},"visiting-team:team-name":{"attribute":"alias"},"visiting-team:team-code":{"attribute":"global-id"},"visiting-team:team-rank":{"attribute":"rank"}}}'

bar = json.loads(foo)
print(json.dumps(bar))

# 解决方案3:使用第三方json解析库

import ujson

foo = '{"root":"cfb-score","children":{"gamecode":{"attribute":"global-id"},"gamestate":{"attribute":"status-id","attribute":"status","attribute":"quarter","attribute":"minutes","attribute":"seconds","attribute":"team-possession-id","attribute":"yards-from-goal","attribute":"down","attribute":"distance","attribute":"segment-number","attribute":"active-state"},"gametype":{"attribute":"type","attribute":"detail"},"stadium":{"attribute":"name","attribute":"city","attribute":"state"},"visiting-team:team-name":{"attribute":"alias"},"visiting-team:team-code":{"attribute":"global-id"},"visiting-team:team-rank":{"attribute":"rank"}}}'

bar = ujson.loads(foo)
print(ujson.dumps(bar))