批量创建JSON配置文件

时间:2016-02-17 10:51:50

标签: python json

我有使用JSON文件作为输入的代码 - JSON文件中的每个条目都是模拟运行的唯一配置。下面是JSON文件的一行(扩展)的简化示例。您可以拥有数千个这样的行,每个行都有不同的唯一值。

{
  "1": {
    "description": "unique configuration 1",
    "attribute to change": 1750,
    "object type 1": {
      "object name": {
        "number": 10,
        "object attribute 1": 5
      }
    },
    "object type 2": {
      "object name": {
        "number": 5,
        "object attribute 1": 50
      }
    }
  }
}

效果很好。但是,每当我希望对配置文件进行更改时,我需要手动执行此操作,如果您有数千个条目,则可能会很乏味。我希望能够加载默认的JSON结构(如上所述)并自动创建所需的变体。

我创建了以下代码,几乎就在那里。

def generate_config_file(input_data, attribute, new_value):

    for key, value in input_data.items():
        if isinstance(value, dict):
            if attribute in value:
                value[attribute] = new_value
            else:
                generate_config_file(value, attribute, new_value)
        elif key == attribute:
            input_data[attribute] = new_value

file_name = input('Enter file name: ')
if len(file_name) < 1:
    file_name = 'default structure.JSON'

    id_num = 1
    out_file = open('new config file.JSON', "a")

    # so here create a new file with multiple rows 
    # where "attribute to change" is the attribute modified
    # here  between 5 and 95 in steps of 5
    for i in range(5, 100, 5):
        with open(file_name) as data_file:
            data = json.load(data_file) 

        # give the new row a unique id_num 
        data[str(id_num)] = data.pop('1')
        generate_config_file(data[str(id_num)], 'attribute to change', i)
        json.dump(data, out_file, sort_keys=True, indent=4)
        id_num += 1

    out_file.close()

我希望输出看起来如下(除了你有19行)。我已经折叠到顶层,但在每一行(1,2,3 .... 19)内,结构应与上面的默认值相匹配。行之间的唯一区别是与要更改的属性关联的值。

{
  "1": {},
  "2": {},
  "3": {} 
}

然而它产生:

{
  "1": {}
}{
  "2": {}
}{
  "3": {} 
}

我尝试过各种各样的事情。例如将输出转换为字符串并尝试去除额外的{}并替换为'。我还尝试了在转储每个输出部分时删除外部{}并替换。既不工作,我现在不确定该尝试什么。

任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

你正在做的是将json数据转储到for循环中,它总是会转储一个字典,它总会产生你现在获得的数据,以解决这个问题。我建议你创建一个像这样的新词典(new_data),

new_data = {}
# so here create a new file with multiple rows 
# where "attribute to change" is the attribute modified
# here  between 5 and 95 in steps of 5
for i in range(5, 100, 5):
    with open(file_name) as data_file:
        data = json.load(data_file) 

    # give the new row a unique id_num 
    data[str(id_num)] = data.pop('1')
    generate_config_file(data[str(id_num)], 'attribute to change', i)
    new_data[str(id_num)] = data[str(id_num)]
    #json.dump(data, out_file, sort_keys=True, indent=4)
    id_num += 1
json.dump(new_data, out_file, sort_keys=True, indent=4)

然后将其转储

答案 1 :(得分:0)

您正在谈论“行”,但您希望这样的字典结构(这是一个有效的 JSON文件):

{
  "1": {},
  "2": {},
  "3": {} 
}

所以我认为最好忘记“行”并总是考虑字典键值对,主要是因为“行”不是JSON standard的一部分,请同时查看validator

在循环中使用:

json.dump(data, out_file, sort_keys=True, indent=4)

在这里以增量模式打开输出文件:

out_file = open('new config file.JSON', "a")`) 

转换为将多个对象堆叠到output.json文本文件中, 这会创建一个无效 JSON文件,就像你指出的那样。

为了避免这种情况,您可以将字典结构一次性写入文件,为此,您可以更改示例代码的第二部分,如下所示:

# parse old config
with open(file_name, "r") as data_file:
    data = json.load(data_file)

# set the new value of attribute_to_change for the first object in json
i = 5

# loop through top level object or what you call rowss
for key in sorted(data.keys()):

    # update the attribute with recursive function on each top level
    # object with an increasing value i
    generate_config_file(data[key], 'attribute to change', i)

    i += 5
    # if you have 19 objects inside your root object in input json 
    # the value will span from 5 to 95

# save the whole modified "data" dictionary in one shot 
out_file_name = 'new config file.JSON'
with open(out_file_name, "w") as out_file:
    json.dump(data, out_file, sort_keys=True, indent=4)