在 Python 中解析嵌套的 Json 以删除列中的特殊字符

Posted

技术标签:

【中文标题】在 Python 中解析嵌套的 Json 以删除列中的特殊字符【英文标题】:Parse Nested Json in Python to Remove Special Characters in Columns 【发布时间】:2019-04-13 00:04:21 【问题描述】:

这是我的 Json 文件


    "highest_table": 
        "items": [
                "key": "Human 1",
                "columns": 
                    "Na$me": "Tom",
                    "Description(ms/2)": "Table Number One on the Top",
                    "A&ge": "24",
                    "Ge_nder": "M"
                
            ,
            
                "key": "Human 2",
                "columns": 
                    "Na$me": "John",
                    "Description(ms/2)": "Table Number One on the Top",
                    "A&ge": "23",
                    "Ge_nder": "M"
                
                
        ]
    

我们的目标是删除列名中的所有特殊字符(或者如果更简单的话,删除 .json 文件中的任何特殊字符),并返回一个 .json 文件。 我最初的想法是将其转换为 pandas,删除列标题中的特殊字符并将其转换回 .json 文件。

这是我迄今为止尝试过的。它们都只打印一行。

import json
from pandas.io.json import json_normalize    

data_file = r"C:\characters.json"

with open(data_file) as data_file:    
    data = json.load(data_file)  

df = json_normalize(data)  

--

data_file = r"C:\characters.json"

df = pd.read_json(data_file)  

如何提取列、删除特殊字符并将它们放回 .json 文件中?

【问题讨论】:

创建 JSON 的原因是什么?这是在你的控制范围内,还是你只需要忍受这种格式? @roganjosh 这是我从中检索此 json 的网站服务器 糟糕的 API :( 你可以用 json 模块做到这一点,但你必须重建整个响应,除非我错过了一个技巧 所以不幸的是我不得不忍受这种格式@roganjosh 正在处理它:) 【参考方案1】:

有点问答 - 您必须为 fixkey 提供完整的实现,但这应该可以解决您的问题。

import json

def fixkey(key):
    # toy implementation
    #print("fixing ".format(key))
    return key.replace("&", "").replace("$", "")

def normalize(data):
    #print("normalizing ".format(data))
    if isinstance(data, dict):
        data = fixkey(key): normalize(value) for key, value in data.items()
    elif isinstance(data, list):
        data = [normalize(item) for item in data]
    return data

jsdata = """

    "highest_table": 
        "items": [
                "key": "Human 1",
                "columns": 
                    "Na$me": "Tom",
                    "Description(ms/2)": "Table Number One on the Top",
                    "A&ge": "24",
                    "Ge_nder": "M"
                
            ,
            
                "key": "Human 2",
                "columns": 
                    "Na$me": "John",
                    "Description(ms/2)": "Table Number One on the Top",
                    "A&ge": "23",
                    "Ge_nder": "M"
                
                
        ]
    

"""


data = json.loads(jsdata)

data = normalize(data)

result = json.dumps(data, indent=2)
print(result)

【讨论】:

很好,我没有发现那条攻击线。 递归是嵌套数据结构的方法;-) @brunodesthuilliers ,使用 sub 而不是 replace 怎么样。如,string = re.sub("!@#$%^&*()[];:,./<>?\|~-=_+"]', '', key) @JimmyStack 正如我所提到的,fixkey 的实现取决于您 - re.sub() 确实是可能的解决方案之一,这取决于您的需求以及您发现最合适的 wrt/可维护性和最终表现(如果这是您的用例的一个问题)。请注意,Python 字符串有一个 translate() 方法,在这里可能更有效。 @brunodesthuilliers 关于您的函数中的第二个elif 的问题。特别是[normalize(item)..。你能解释一下那部分是做什么的吗?是否再次规范化调用该函数?【参考方案2】:

坦率地说,这,但我还没有找到更通用的方法。这对于您的特定 JSON 非常具体(这个问题确实需要在 API 中解决)。

import json


response = """
    "highest_table": 
        "items": [
                "key": "Human 1",
                "columns": 
                    "Na$me": "Tom",
                    "Description(ms/2)": "Table Number One on the Top",
                    "A&ge": "24",
                    "Ge_nder": "M"
                
            ,
            
                "key": "Human 2",
                "columns": 
                    "Na$me": "John",
                    "Description(ms/2)": "Table Number One on the Top",
                    "A&ge": "23",
                    "Ge_nder": "M"
                
                
        ]
    
"""

def fix_json(resp):

    output = 'highest_table': 'items': []
    for item in resp['highest_table']['items']:
        inner_dict = item['columns']
        fixed_values = 'Name': inner_dict['Na$me'],
                        'Description(ms/2)': inner_dict['Description(ms/2)'],
                        'Age': inner_dict['A&ge'],
                        'Gender': inner_dict['Ge_nder']
                        
        new_inner = 'key': item['key'], 'columns': fixed_values
        output['highest_table']['items'].append(new_inner)
    return output



response = json.loads(response)
fixed = fix_json(response)

【讨论】:

谢谢你的回答,2个问题,1)你为什么说真正的问题在.api中? api有什么问题?第二个问题,不是物理删除这三列的特殊字符,我们可以让它成为列的循环并删除特殊字符吗? "你为什么说真正的问题出在 .api" => 因为它返回丑陋的(即使在技术上是有效的)json。 @JimmyStack 1) 因为当您使用的 API 生成响应时,损害已经造成。数据提供者解决这个问题要简单得多(这些字符在键中没有逻辑位置)。 2) 我不相信我能做出一个更通用的解决方案来修复任意嵌套的结构。 "我们可以让它循环到列并删除特殊字符吗?" => 参考我自己的答案以获得更通用的解决方案。

以上是关于在 Python 中解析嵌套的 Json 以删除列中的特殊字符的主要内容,如果未能解决你的问题,请参考以下文章

Logstash 解析Json字符串,删除json嵌套字段

使用包含嵌套 JSON 字符串的一列解析 Pandas DataFrame 中的列

在 Python 中通过嵌套的 Json/dict 解析

解析嵌套的 json 并将其保存在 csv 中

系统运维系列 之Java语言中解析json嵌套数组(干货亲测)

SQL:LATERAL VIEW函数解析多嵌套的json