2016-02-17 3 views
1

У меня есть код, который использует 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": {} 
} 

Я пробовал различные вещи. Например, преобразование вывода в строку и попытка вырезать дополнительные {} и заменить на. Я также пробовал при сбросе каждого раздела вывода o удалить внешний {} и заменить. Ни работали, и я теперь не уверен, что попробовать.

Любая помощь приветствуется.

ответ

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) 

и сбросить его после

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)