【问题标题】:json.loads with wrong format input stringjson.loads 输入字符串格式错误
【发布时间】:2012-02-24 12:46:14
【问题描述】:

在这种输入字符串上到达json.loads 的最快方式(执行方式)是什么:

istr=""" {u'topic': u'dl_job', u'url': u'http://somedomain.com' }"""

我对传递为 istr 的内容没有太多控制权。

注意事项:

  • json.loads 不喜欢前导u
  • 也不喜欢用'而不是"分隔字符串

更新:我知道我可以玩一些肮脏的把戏,比如替换 u',但我想知道是否有更清洁的解决方案。

【问题讨论】:

  • 您缺乏控制意味着您可能还会遇到类似的情况:istr=""" {u'topic': u'dl_j"""?
  • 你拥有的不是json,所以你不能真正将它加载为json。如果它是 Python 数据结构(看起来像一个),您可以使用 ast.literal_eval,但不会喜欢缺少的 }

标签: python json


【解决方案1】:

如果这是一个 Python 数据结构(看起来像),你想要的函数是ast.literal_eval

http://docs.python.org/library/ast#ast.literal_eval

这类似于只调用eval,但literal_eval 是安全的,因为它不会调用任何函数或任何东西,只是解析文字(即列表、字典、字符串、数字等)。

【讨论】:

    【解决方案2】:

    如果您可以信任输入,则 eval() 似乎比 naïve replace 快两倍。但是,所涉及的风险可能不值得性能提升。 (编辑:感谢 J.F. Sebastian / Thomas K,添加了 literal_eval 时间。)

    from timeit import timeit
    
    timeit(lambda: json.loads(istr.replace("'", "\"").replace("u\"", "\"")), number=10000)
    0.69373106956481934
    
    # UNSAFE
    timeit(lambda: eval(istr), number=10000)
    0.27783799171447754
    
    # literal_eval accepts only strings, numbers, tuples, lists, dicts, booleans, and None
    timeit(lambda: ast.literal_eval(istr.strip()), number=10000)
    0.4245460033416748
    

    (我认为 isr 末尾缺少的 } 是一个错字。)

    【讨论】:

    • -1:不要在您无法控制的字符串上使用eval()。请改用ast.literal_eval()
    【解决方案3】:

    JSON 是 JSON。它具有构成有效 JSON 字符串的正式规范。 json.loads 不从字符串加载 python 字典,它从字符串加载 JSON。尝试加载其他内容通常会给您带来麻烦,是的,会导致黑客入侵。

    如果你想评估 python 字典,我建议 Thomas K 的评论,或者只是 eval()。

    【讨论】:

      猜你喜欢
      • 2012-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多