Удалить элемент в объекте JSON

Я пытаюсь просмотреть список объектов, удаляя элемент из каждого объекта. Каждый объект представляет собой новую строку. Затем я пытаюсь сохранить новый файл как есть без элемента, содержащегося в объектах. Я знаю, что это, вероятно, простая задача, но я не могу не получить эту работу. Был бы признателен, если бы кто-то мог предложить руку. Спасибо.

{
"business_id": "fNGIbpazjTRdXgwRY_NIXA",
"full_address": "1201 Washington Ave\nCarnegie, PA 15106",
"hours": {
    "Monday": {
        "close": "23:00",
        "open": "11:00"
    },
    "Tuesday": {
        "close": "23:00",
        "open": "11:00"
    },
    "Friday": {
        "close": "23:00",
        "open": "11:00"
    },
    "Wednesday": {
        "close": "23:00",
        "open": "11:00"
    },
    "Thursday": {
        "close": "23:00",
        "open": "11:00"
    },
    "Saturday": {
        "close": "23:00",
        "open": "11:00"
    }
},
"open": true,
"categories": ["Bars", "American (Traditional)", "Nightlife", "Lounges", "Restaurants"],
"city": "Carnegie",
"review_count": 7,
"name": "Rocky's Lounge",
"neighborhoods": [],
"longitude": -80.0849416,
"state": "PA",
"stars": 4.0,
"latitude": 40.3964688,
"attributes": {
    "Alcohol": "full_bar",
    "Noise Level": "average",
    "Music": {
        "dj": false
    },
    "Attire": "casual",
    "Ambience": {
        "romantic": false,
        "intimate": false,
        "touristy": false,
        "hipster": false,
        "divey": false,
        "classy": false,
        "trendy": false,
        "upscale": false,
        "casual": false
    },
    "Good for Kids": true,
    "Wheelchair Accessible": true,
    "Good For Dancing": false,
    "Delivery": false,
    "Dogs Allowed": false,
    "Coat Check": false,
    "Smoking": "no",
    "Accepts Credit Cards": true,
    "Take-out": true,
    "Price Range": 1,
    "Outdoor Seating": false,
    "Takes Reservations": false,
    "Waiter Service": true,
    "Wi-Fi": "free",
    "Caters": false,
    "Good For": {
        "dessert": false,
        "latenight": false,
        "lunch": false,
        "dinner": false,
        "brunch": false,
        "breakfast": false
    },
    "Parking": {
        "garage": false,
        "street": false,
        "validated": false,
        "lot": true,
        "valet": false
    },
    "Has TV": true,
    "Good For Groups": true
},
"type": "business"

}

Мне нужно удалить информацию, содержащуюся в элементе hours, однако информация не всегда одинакова. Некоторые содержат все дни, а некоторые содержат информацию только об одном или двух днях. Код, который я пытался использовать, - это Pyton, который я ищу в течение дня, чтобы использовать его для решения моей проблемы. Я не очень хорошо разбираюсь в Python. Любая помощь будет оценена по достоинству.

import json

with open('data.json') as data_file:
data = json.load(data_file)
for element in data: 
        del element['hours']

Извините, просто чтобы добавить ошибку, которую я получаю при запуске кода: TypeError: объект 'unicode' не поддерживает удаление элемента


person Bradley    schedule 13.04.2016    source источник
comment
Вы хотите удалить все ключи и значения часов? (дни,закрыть,открыть) или просто какое-то поле в нем?   -  person lc123    schedule 13.04.2016
comment
Привет, Ic123, Да, я хотел бы избавиться от всех данных внутри, включая элемент часов, чтобы он больше не был виден. У меня есть список из 20 000 объектов, которые начинаются с новой строки каждый раз, когда мне нужно попытаться выполнить цикл и удалить часы и все внутри этого элемента для всего файла. Нужно ли будет записывать результаты в новый выходной файл? или код должен редактировать текущий файл? Любые направления будут оценены.   -  person Bradley    schedule 13.04.2016
comment
Привет, @Bradley, после того, как вы удалите ключ hour, как предложил @Apero, вам нужно записать результат в новый файл или даже перезаписать старый файл. иначе ваш файл не будет «знать» ваши изменения   -  person lc123    schedule 13.04.2016
comment
file = open(newfile.json, w) file.write(data) Что-то вроде этого не работает. Извините, если я сталкиваюсь с ленивым на этом. Я буквально пытаюсь изменить файл для использования в Pig, так как я не могу заставить файлы jar слоновой птицы работать вообще. Я могу кормить Свинью только с помощью одного отступа в файле JSON. На самом деле я понятия не имею, как использовать Python, но весь день пытался найти что-то, что можно было бы использовать для управления моим файлом JSON. Спасибо @Ic123   -  person Bradley    schedule 13.04.2016


Ответы (2)


Предположим, вы хотите перезаписать тот же файл:

import json

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

for element in data:
    element.pop('hours', None)

with open('data.json', 'w') as data_file:
    data = json.dump(data, data_file)

dict.pop(<key>, not_found=None), вероятно, то, что вы искали, если я понял ваши требования. Потому что он удалит ключ hours, если он присутствует, и не выйдет из строя, если его нет.

Однако я не уверен, что понимаю, почему для вас имеет значение, содержит ли ключ часов несколько дней или нет, потому что вы просто хотите избавиться от всей пары ключ/значение, верно?

Теперь, если вы действительно хотите использовать del вместо pop, вот как вы можете заставить свой код работать:

import json

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

for element in data:
    if 'hours' in element:
        del element['hours']

with open('data.json', 'w') as data_file:
    data = json.dump(data, data_file)

EDIT Итак, как видите, я добавил код для записи данных обратно в файл. Если вы хотите записать его в другой файл, просто измените имя файла во втором операторе open.

Мне пришлось изменить отступ, как вы могли заметить, чтобы файл был закрыт на этапе очистки данных и его можно было перезаписать в конце.

with — это то, что называется менеджером контекста, все, что он предоставляет (здесь дескриптор файла data_file), доступно ТОЛЬКО в этом контексте. Это означает, что как только отступ блока with заканчивается, файл закрывается и контекст заканчивается вместе с файловым дескриптором, который становится недействительным/устаревшим.

Без этого вы не сможете открыть файл в режиме записи и получить новый файловый дескриптор для записи.

Надеюсь, достаточно ясно...

ВТОРАЯ ПРАВКА

На этот раз кажется очевидным, что вам нужно сделать это:

with open('dest_file.json', 'w') as dest_file:
    with open('source_file.json', 'r') as source_file:
        for line in source_file:
            element = json.loads(line.strip())
            if 'hours' in element:
                del element['hours']
            dest_file.write(json.dumps(element))
person DevLounge    schedule 13.04.2016
comment
Привет Apero, Спасибо за ваш быстрый ответ. Итак, у меня есть список из 20 000 тысяч объектов в файле, и мне нужно полностью удалить элемент, если это возможно, чтобы объекты не содержали никаких ссылок на время или день. Проблема в том, что у некоторых объектов есть часы и дни, а некоторые просто пустые {} Я запустил приведенный выше код, чтобы попробовать удалить их, но я что-то упустил? Все заработало, но файл не изменился. Я знаю, что звучу здесь глупо, поскольку я, вероятно, должен хранить и записывать новые данные в другой файл? В очередной раз благодарим за помощь - person Bradley; 13.04.2016
comment
о, конечно, здесь я изменяю только элементы списка data, так что это в памяти. Вы должны записать это в конце с помощью json.dump. либо вы перезаписываете тот же файл, либо записываете его в новый, на ваш выбор. - person DevLounge; 13.04.2016
comment
Является ли сохранение результата json.dump() ошибкой? насколько мне известно, json.dump() не имеет задокументированного возвращаемого значения. - person Robᵩ; 13.04.2016
comment
что вам нужно, чтобы вернуть? его результат - это просто файл, который он написал, нет? - person DevLounge; 13.04.2016
comment
Привет Apero, Это имеет гораздо больше смысла, хорошо. Спасибо. Я получаю сообщение об ошибке, основанное на том, что объект «Unicode» не поддерживает удаление элемента. [Разработка (мастер)]$ python jsonedit.py Трассировка (последний последний вызов): файл jsonedit.py, строка 8, в ‹module› del element['hours'] TypeError: объект 'unicode' не поддерживает удаление элемента - person Bradley; 13.04.2016
comment
@Apero, да, я просто хочу открыть файл, в котором есть множество объектов, содержащих часы элемента внутри него. Затем я хочу выполнить поиск по каждому объекту (который начинается с новой строки) и удалить элемент часа и все, что внутри него, чтобы его больше не было. Затем я хотел бы сохранить новый файл, содержащий все объекты, но без удаления элемента. Извините, если я здесь больно об этом. Сначала я разместил только одно описание объекта, но есть список объектов, начинающихся с { в каждой строке. - person Bradley; 13.04.2016
comment
хорошо, понял, ваш файл действительно похож на экспорт mongodb, где каждая строка является элементом json, но ваш файл не содержит список элементов json, как обычно. Тогда позвольте мне отредактировать мой ответ - person DevLounge; 13.04.2016
comment
Если мое последнее редактирование — это то, что вам нужно, я уберу все остальное, и мы также можем удалить все эти комментарии. - person DevLounge; 13.04.2016
comment
он сказал RuntimeError: словарь изменил размер во время итерации - person Kardi Teknomo; 24.04.2019
comment
Этот element = json.loads(line.strip()), похоже, выдает мне ошибку, хотя мой файл выглядит как OP. Интересно, как эта строка справляется со строками, содержащими только скобки. Кроме того, мне интересно, как json.dumps работает с этими строками. - person bomben; 28.08.2020
comment
если вы использовали del element[key] в итерируемом цикле for, вы получите сообщение об ошибке, что структура изменилась - person Golden Lion; 05.02.2021
comment
Я удаляю ключ в словаре, который представляет элемент списка, поэтому размер списка не меняется во время итерации. Итератор списка возвращает каждый элемент (тот, из которого мы удаляем ключ), поэтому размер списка НЕ ​​меняется во время итерации. - person DevLounge; 25.02.2021

with open('writing_file.json', 'w') as w:
    with open('reading_file.json', 'r') as r:
        for line in r:
            element = json.loads(line.strip())
            if 'hours' in element:
                del element['hours']
            w.write(json.dumps(element))

это метод, который я использую ..

person Billy    schedule 15.11.2020