【问题标题】:How to parse and sort JSON with multiple keys in Python如何在 Python 中使用多个键解析和排序 JSON
【发布时间】:2017-11-20 17:42:57
【问题描述】:

实际使用 JSON 进行培训,试图了解如何使用两个不同的键解析新的 JSON。我想对一些日志进行排序以用于数据可视化。

我的数据 JSON

{
            "productTitle": "Product",
            "apiName": "soapwebservice"
            "statusCode": "200 OK"
},
{
            "productTitle": "Product",
            "apiName": "productionservice",
            "statusCode": "200 OK"
},
{
            "productTitle": "Product",
            "apiName": "firstapi",
            "statusCode": "200 OK"
},          
{
            "productTitle": "Product",
            "apiName": "firstapi",
            "statusCode": "200 OK"
}, 
{
            "productTitle": "Suitability",
            "apiName": "suitability-api",
            "statusCode": "200 OK"
}

预期的输出 JSON:

{
    "Product": 4,
    "api-activity": {
         "soapwebservice": 1,
         "productionservice": 1,
         "firstapi": 2
    }
}
{
    "Suitability": 1,
    "api-activity": {
         "suitability-api": 1,
    }
}

这是我第一个解析和计算第一个键的代码:

import json
from collections import Counter

with open('events1.json') as json_data:
    json_obj = json.load(json_data) # Read the JSON file

    # print(json_obj['calls'][0]['appName']); #Example JSON Extract
    c = Counter(player['productTitle'] for player in json_obj['calls'])

with open('output.json', 'w') as f:
    f.write(json.dumps(c, indent=4)) # Parse and write the file

print("Translation of JSON");

我正在寻找一种获取预期 JSON 的方法,可能带有一个循环,如下所述:parse JSON values by multilevel keys 但是我无法按预期获取 JSON,您知道吗?

【问题讨论】:

    标签: python json


    【解决方案1】:

    使用itertools.groupby() 按所需属性对元素进行分组。第一个按产品标题分组,然后在每个结果组中,再次对元素进行分组,但现在按 api 名称分组。所需的计数器只是每个结果组中元素的数量:

    import itertools
    import json
    
    def by_product_title(data):
        return data['productTitle']
    
    def by_api_name(data):
        return data['apiName']
    
    json_str = '''
    [
        {
            "productTitle": "Product",
            "apiName": "soapwebservice",
            "statusCode": "200 OK"
        },
        {
            "productTitle": "Product",
            "apiName": "productionservice",
            "statusCode": "200 OK"
        },
        ...
    ]
    '''
    
    data = json.loads(json_str)
    grouped_by_product_title = itertools.groupby(sorted(data, key=by_product_title), by_product_title)
    for product, group in grouped_by_product_title:
        elements = list(group)
        grouped_by_api_name = itertools.groupby(sorted(elements, key=by_api_name), by_api_name)
        api_activity = {key: len(list(val)) for key, val in grouped_by_api_name}
        output = {product: len(elements), 'api-activity': api_activity}
        json_output = json.dumps(output, sort_keys=True, indent=4)
        print(json_output)
    

    输出:

    {
        "Product": 4,
        "api-activity": {
            "firstapi": 2,
            "productionservice": 1,
            "soapwebservice": 1
        }
    }
    {
        "Suitability": 1,
        "api-activity": {
            "suitability-api": 1
        }
    }
    

    【讨论】:

    • 谢谢,它就像一个魅力。就我而言,当我使用 JSON 文件时,我必须使用 json.load 而不是 json.loads 来调用它,以防万一有人也尝试您的代码。
    • 使用 itertools 的多级 groupby 的好例子。
    【解决方案2】:

    我确实喜欢这个。看看吧。

    import json
    
    json_str = """
    [
    {
                "productTitle": "Product",
                "apiName": "soapwebservice",
                "statusCode": "200 OK"
    },
    {
                "productTitle": "Product",
                "apiName": "productionservice",
                "statusCode": "200 OK"
    },
    {
                "productTitle": "Product",
                "apiName": "firstapi",
                "statusCode": "200 OK"
    },
    {
                "productTitle": "Product",
                "apiName": "firstapi",
                "statusCode": "200 OK"
    },
    {
                "productTitle": "Suitability",
                "apiName": "suitability-api",
                "statusCode": "200 OK"
    }
    ]
    """
    
    data_set = json.loads(json_str)
    data_list = []
    for data in data_set:
        title = data["productTitle"]
        exist = False
        for existing_data in data_list:
            if title in existing_data:
                exist = True
                existing_data[title] += 1
                if data["apiName"] in existing_data["api-activity"]:
                    existing_data["api-activity"][data["apiName"]] += 1
                else:
                    existing_data["api-activity"][data["apiName"]] = 1
        if not exist:
            new = dict()
            new[data["productTitle"]] = 1
            new["api-activity"] = dict()
            new["api-activity"][data["apiName"]] = 1
            data_list.append(new)
    
    print(json.dumps(data_list))
    

    【讨论】:

      【解决方案3】:

      您的第一个问题是 json.load(和 json.loads)只会从文件中获取一个元素。要解决此问题,您需要将其转换为列表。

      [
        {
          "productTitle": "Product",
          "apiName": "soapwebservice",
          "statusCode": "200 OK"
        },
        {
          "productTitle": "Product",
          "apiName": "productionservice",
          "statusCode": "200 OK"
        },
        {
          "productTitle": "Product",
          "apiName": "firstapi",
          "statusCode": "200 OK"
        },
        {
          "productTitle": "Product",
          "apiName": "firstapi",
          "statusCode": "200 OK"
        },
        {
          "productTitle": "Suitability",
          "apiName": "suitability-api",
          "statusCode": "200 OK"
        }
      ]
      

      您的第二个问题是您试图访问不存在的 json_obj['calls'] 。通过删除访问器,您将获得以下代码:

      import json
      from collections import Counter
      
      with open('events1.json') as json_data:
          json_obj = json.load(json_data) # Read the JSON file
          c = Counter(player['productTitle'] for player in json_obj)
      
      with open('output.json', 'w') as f:
          f.write(json.dumps(c, indent=4)) # Parse and write the file
      
      print("Translation of JSON");
      

      这会在 output.json 中产生以下输出:

      {
        "Product": 4, 
        "Suitability": 1
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-01
        • 1970-01-01
        • 2021-10-31
        相关资源
        最近更新 更多