【问题标题】:Parsing and printing JSON data using Python使用 Python 解析和打印 JSON 数据
【发布时间】:2016-10-25 11:31:18
【问题描述】:

我是 JSON 新手,我正在使用 Python 从 JSON 数据中提取值。我正在使用另一个带有 cURL 的 shell 脚本获取 JSON 数据。

这是我从 shell 脚本(称为 test.sh)的 JSON 输出:

{"preview":true,"offset":0,"result":{"Country":"AU","count":"417"}}
{"preview":true,"offset":1,"result":{"Country":"BG","count":"7"}}
{"preview":true,"offset":2,"result":{"Country":"CA","count":"198"}}
{"preview":true,"offset":3,"result":{"Country":"CH","count":"1"}}
{"preview":true,"offset":4,"result":{"Country":"CN","count":"3"}}
{"preview":true,"offset":5,"result":{"Country":"CR","count":"1"}}
{"preview":true,"offset":6,"result":{"Country":"DE","count":"148"}}
{"preview":true,"offset":7,"result":{"Country":"DK","count":"1"}}
{"preview":true,"offset":8,"result":{"Country":"FI","count":"1"}}
{"preview":true,"offset":9,"result":{"Country":"FR","count":"1052"}}
{"preview":true,"offset":10,"result":{"Country":"GB","count":"1430"}}
{"preview":true,"offset":11,"result":{"Country":"HK","count":"243"}}
{"preview":false,"offset":12,"lastrow":true,"result":{"Country":"VG","count":"54"}}

我想将所有“Country”值和“count”值打印成这样的:

AU 417
BG 7
CA 198
...

为了做到这一点,我创建了一个循环来获取和打印所有需要的值,但是我得到了这个错误:

 AttributeError: 'str' object has no attribute 'read'

这是我的python代码:

import subprocess
import json
import sys
import subprocess
answer = subprocess.check_output(['./test.sh']) #test.sh contains the cURL command
json_obj = json.load(answer)
for i in json_obj['result']:
    print i['Country']
    print i['count']

我在这里错过了什么吗?

任何帮助将不胜感激, 非常感谢

【问题讨论】:

  • 如果你有一个字符串,你应该使用json.loads。另请注意,您的输出实际上不是有效的 JSON(或者,它是多个 JSON 对象,我认为 json 要么只解析第一个对象,要么向您抱怨)。
  • 我觉得Python的json很严格。尝试在引号之间加上真假和数字
  • @Goufalite true、false、数字等都是有效的JSON值
  • @Goufalite 反正这不是问题。
  • 是的,因为您没有一个有效的 JSON 对象。如果要返回多个对象,请将它们放入一个数组中(即以[ 开头,以] 结尾,每个对象之间以, 结尾,就像Python 列表一样)。或loads 一次一行/一个对象。

标签: python json curl


【解决方案1】:

我在帖子中看到了一些错误或误解的内容:

  1. 如果您有一组 JSON 对象,则应将它们设为对象数组,或将它们一次解析为单独的文件或一个文件中的单独行(不推荐)。前者会更容易、更可靠:

    [{"obj":1},{"obj":2},...]
    
  2. 如果您直接从字符串而不是文件加载,则应使用 json.loads 而不是 json.load

  3. 这是一个工作示例:

    import json
    
    answers = '[{"preview":true,"offset":0,"result":{"Country":"AU","count":"417"}}' + \
              ',{"preview":true,"offset":1,"result":{"Country":"BG","count":"7"}}]'
    json_obj = json.loads(answers)
    
    for i in json_obj:
        print i['result']['Country'], i['result']['count']
    

【讨论】:

    【解决方案2】:

    您的数据是多个 json 对象。

    您可能希望将其用大括号括起来({}),并将其视为所有对象的唯一集合。

    {
    {"preview":true,"offset":0,"result":{"Country":"AU","count":"417"}}
    {"preview":true,"offset":1,"result":{"Country":"BG","count":"7"}}
    {"preview":true,"offset":2,"result":{"Country":"CA","count":"198"}}
    {"preview":true,"offset":3,"result":{"Country":"CH","count":"1"}}
    {"preview":true,"offset":4,"result":{"Country":"CN","count":"3"}}
    {"preview":true,"offset":5,"result":{"Country":"CR","count":"1"}}
    {"preview":true,"offset":6,"result":{"Country":"DE","count":"148"}}
    {"preview":true,"offset":7,"result":{"Country":"DK","count":"1"}}
    {"preview":true,"offset":8,"result":{"Country":"FI","count":"1"}}
    {"preview":true,"offset":9,"result":{"Country":"FR","count":"1052"}}
    {"preview":true,"offset":10,"result":{"Country":"GB","count":"1430"}}
    {"preview":true,"offset":11,"result":{"Country":"HK","count":"243"}}
    {"preview":false,"offset":12,"lastrow":true,"result":{"Country":"VG","count":"54"}}
    }
    

    【讨论】:

    • 那是完全无效的 JSON。应该使用对象数组[{},{},{}...]
    【解决方案3】:

    对于结果输出

    {"preview":true,"offset":0,"result":{"Country":"AU","count":"417"}}
    {"preview":true,"offset":1,"result":{"Country":"BG","count":"7"}}
    {"preview":true,"offset":2,"result":{"Country":"CA","count":"198"}}
    {"preview":true,"offset":3,"result":{"Country":"CH","count":"1"}}
    {"preview":true,"offset":4,"result":{"Country":"CN","count":"3"}}
    {"preview":true,"offset":5,"result":{"Country":"CR","count":"1"}}
    

    实际上有几行 doc(单个 json)。 您应该逐行阅读它们,而不是逐行阅读。

    这是建议。您可以暂时保存 JSON 文档,然后阅读并加载它们。

    1. 保存test.sh > tmp.txt
    2. 逐行阅读

    with open('tmp.txt', 'r') as f: for i in f: doc = f.readline() try: the_dict = json.loads(doc) print(the_dict['Country']) except Exception, e: print(str(e)) 或者如果你坚持使用子进程,你仍然可以逐行读取文件。只要记住你得到的输出是一个列表。您应该使用循环来迭代所有内容。

    【讨论】:

      【解决方案4】:

      简单的解决方案是, 让我们从你的答案开始:

      answer = '''{"preview":true,"offset":0,"result":{"Country":"AU","count":"417"}}
      {"preview":true,"offset":1,"result":{"Country":"BG","count":"7"}}
      {"preview":true,"offset":2,"result":{"Country":"CA","count":"198"}}
      {"preview":true,"offset":3,"result":{"Country":"CH","count":"1"}}
      {"preview":true,"offset":4,"result":{"Country":"CN","count":"3"}}
      {"preview":true,"offset":5,"result":{"Country":"CR","count":"1"}}
      {"preview":true,"offset":6,"result":{"Country":"DE","count":"148"}}
      {"preview":true,"offset":7,"result":{"Country":"DK","count":"1"}}
      {"preview":true,"offset":8,"result":{"Country":"FI","count":"1"}}
      {"preview":true,"offset":9,"result":{"Country":"FR","count":"1052"}}
      {"preview":true,"offset":10,"result":{"Country":"GB","count":"1430"}}
      {"preview":true,"offset":11,"result":{"Country":"HK","count":"243"}}
      {"preview":false,"offset":12,"lastrow":true,"result":{"Country":"VG","count":"54"}}'''
      

      将其转换为有效的 json

      import json
      answer = json.loads('['+answer.replace('\n',',')+']')
      

      打印你的结果:

      for i in answer:
          print i['result']['Country'],i['result']['count']
      
      AU 417
      BG 7
      CA 198
      CH 1
      CN 3
      CR 1
      DE 148
      DK 1
      FI 1
      FR 1052
      GB 1430
      HK 243
      VG 54
      

      所以你的完整代码是:

      import subprocess
      import json
      answer = subprocess.check_output(['./test.sh'])
      answer = json.loads('['+answer.replace('\n',',')+']')
      for i in answer:
          print i['result']['Country'],i['result']['count']
      

      【讨论】:

        【解决方案5】:

        请将代码存入test.py,数据存入test.json

        test.py

        import json
        
        
        with open('/tmp/test.json') as f:
            for i in f:
                data = json.loads(i)
                print("{Country} {count}".format(**data["result"]))
        

        test.json

        $ python test.py
        AU 417
        BG 7
        CA 198
        CH 1
        CN 3
        CR 1
        DE 148
        DK 1
        FI 1
        FR 1052
        GB 1430
        HK 243
        VG 54
        

        你也可以在你的 prog 中试一试:

        for i in answer:
            data = json.loads(i)
            print("{Country} {count}".format(**data["result"]))
        

        【讨论】:

        • 感谢就像一个魅力!我很困惑,因为我认为返回的数据是单个 JSON 对象,但我错了。直到!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-08
        • 1970-01-01
        • 1970-01-01
        • 2018-10-05
        • 1970-01-01
        • 1970-01-01
        • 2012-10-14
        相关资源
        最近更新 更多