【问题标题】:Editing Json Program编辑 Json 程序
【发布时间】:2021-07-02 11:59:36
【问题描述】:

我的代码获取一个 json 路径文件,打开/解析它并在设置的 csv 映射文件的帮助下打印出所需的值(知道要查找的关键字和打印值的名称)。

然而,一些 json 文件有多个值,例如,带有“Affiliate”键的 json 文件内部将有更多的键/值对,而不仅仅是一个值。

如何在像这样的键中解析并打印出“真”值与“假”值?目前,我的代码将打印出该目标键中的整个键值对数组。

示例 json:

"Affiliate": [
    {
        "ov": true,
        "value": "United States",
        "lookupCode": "US"
    },
    {
        "ov": false,
        "value": "France",
        "lookupCode": "FR"
    }
]

我的代码:

import json
import csv

output_dict = {}

#maps csv and json information 
def findValue(json_obj, target_key, output_key):
    for key in json_obj:
        if isinstance(json_obj[key], dict):
            findValue(json_obj[key], target_key, output_key)
        else:
            if target_key == key:
                output_dict[output_key] = json_obj[key]

#Opens and parses json file
file = open('source_data.json', 'r')
json_read = file.read()
obj = json.loads(json_read)

#Opens and parses csv file (mapping)
with open('inputoutput.csv') as csvfile:
    fr = csv.reader(csvfile)
    for row in fr:
        findValue(obj, row[0], row[1])

#creates/writes into json file 
with open("output.json", "w") as out: 
    json.dump(output_dict, out, indent=4)

【问题讨论】:

  • 您能否将inputoutput.csv 的相关行添加到您的问题中?此外,您不会关闭source_data.json。我建议你在那里也使用with open 模式......
  • @Edo Akse csv 文件将只包含像“LastModifiedDate,date_modified”这样的行,其中第一个输入是目标键,第二个是输出键
  • 我不确定最终结果应该是 ATM。您不想打印出键 Affiliate 的整个值,但是如何确定要输出值列表的哪一部分?
  • 是的,所以基本上 csv 文件会告诉程序还要寻找什么关键词,所以在“附属”这样的情况下,我想我必须改变程序,以便它检查值关键字“ov”为真,如果为真,则返回与真 ov 对应的关键字“值”的值/有效负载。只是一些最终的上下文,程序创建并放置值(我们在 json 中搜索),以及它们对应的输出词(我们给它们),因此 csv 文件将是 Affiliate、Cntr 和创建的 json 文件看起来类似“Cntr”{美国}

标签: python json csv


【解决方案1】:

因此,您需要更改映射 CSV 的结构方式,因为您需要变量来确定要满足哪些条件,以及在满足条件时返回哪个值...

请注意,在下面实现的逻辑中,如果Affiliate 中有两个列表项都将键ov 设置为true,则只会添加最后一个(字典键是唯一的)。你可以在我在代码中注释的地方放一个return,但它当然只会使用第一个。

我已将 CSV 重组如下:

inputoutput.csv

Affiliate,Cntr,ov,true,value
Sample1,Output1,,,
Sample2,Output2,criteria2,true,returnvalue

我用作源数据的 JSON 是这个:

source_data.json

{
    "Affiliate": [
        {
            "ov": true,
            "value": "United States",
            "lookupCode": "US"
        },
        {
            "ov": false,
            "value": "France",
            "lookupCode": "FR"
        }
    ],
    "Sample1": "im a value",
    "Sample2": [
        {
            "criteria2": false,
            "returnvalue": "i am not a return value"
        },
        {
            "criteria2": true,
            "returnvalue": "i am a return value"
        }
    ]
}

实际代码如下,注意我对我的选择做了一些评论。

ma​​in.py

import json
import csv


output_dict = {}


def str2bool(input: str) -> bool:
    """simple check to see if a str is a bool"""
    # shamelessly stolen from:
    # https://stackoverflow.com/a/715468/9267296
    return input.lower() in ("yes", "true", "t", "1")


def findValue(
    json_obj,
    target_key,
    output_key,
    criteria_key=None,
    criteria_value=False,
    return_key="",
):
    """maps csv and json information"""
    # ^^ use PEP standard for docstrings:
    # https://www.python.org/dev/peps/pep-0257/#id16

    # you need to global the output_dict to avoid weirdness
    # see https://www.w3schools.com/python/gloss_python_global_scope.asp
    global output_dict

    for key in json_obj:
        if isinstance(json_obj[key], dict):
            findValue(json_obj[key], target_key, output_key)

        # in this case I advise to use "elif" instead of the "else: if..."
        elif target_key == key:
            # so this is the actual logic change.
            if isinstance(json_obj[key], list):
                for item in json_obj[key]:
                    if (
                        criteria_key != None
                        and criteria_key in item
                        and item[criteria_key] == criteria_value
                    ):
                        output_dict[output_key] = item[return_key]
                        # here you could put a return
            else:
                # this part doesn't change
                output_dict[output_key] = json_obj[key]
                # since we found the key and added in the output_dict
                # you can return here to slightly speed up the total
                # execution time
                return


# Opens and parses json file
with open("source_data.json") as sourcefile:
    json_obj = json.load(sourcefile)


# Opens and parses csv file (mapping)
with open("inputoutput.csv") as csvfile:
    fr = csv.reader(csvfile)
    for row in fr:
        # this check is to determine if you need to add criteria
        # row[2] would be the key to check
        # row[3] would be the value that the key need to have
        # row[4] would be the key for which to return the value
        if row[2] != "":
            findValue(json_obj, row[0], row[1], row[2], str2bool(row[3]), row[4])
        else:
            findValue(json_obj, row[0], row[1])


# Creates/writes into json file
with open("output.json", "w") as out:
    json.dump(output_dict, out, indent=4)

使用我提供的输入文件运行上述代码,生成以下文件:

output.json

{
    "Cntr": "United States",
    "Output1": "im a value",
    "Output2": "i am a return value"
}

我知道有一些方法可以优化它,但我想让它接近原始版本。您可能需要使用将内容添加到 output_dict 的确切方式来获得您想要的确切输出 JSON...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    • 2014-11-24
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多