#python #json #python-3.x
#python #json #python-3.x
Вопрос:
У меня есть следующий JSON:
{
"1605855600000":
[
{
"id": "1",
"value": "1. Choice 1",
"checked": true
},
{
"id": "2",
"value": "2. Choice 2",
"checked": false
},
{
"id": "3",
"value": "3. Choice 3",
"checked": false
},
{
"id": "4",
"value": "4. Choice 4",
"checked": false
},
{
"id": "5",
"value": "5. Choice 5",
"checked": false
}
],
"1604732400000":
[
{
"id": "1",
"value": "1. Choice 1",
"checked": false
},
{
"id": "2",
"value": "2. Choice 2",
"checked": false
},
{
"id": "3",
"value": "3. Choice 3",
"checked": false
},
{
"id": "4",
"value": "4. Choice 4",
"checked": false
},
{
"id": "5",
"value": "5. Choice 5",
"checked": false
}
]
}
Я не уверен в точной терминологии, но «ключи», такие как «1605855600000» и «1604732400000», являются временными метками UNIX, которые мне нужно преобразовать в Python.
Вот что у меня есть до сих пор:
def convert_timestamp(obj):
for key in obj.keys():
timestamp = int(key) / 1000
dt_object = datetime.fromtimestamp(timestamp)
date = dt_object.strftime("%B %d, %Y")
new_key = date
if new_key != key:
obj[new_key] = obj[key]
del obj[key]
return obj
data = json.loads(data, object_hook=convert_timestamp)
Однако ошибка, которую я получаю, гласит:
ValueError: invalid literal for int() with base 10: 'id'
это означает, что он обращается к уровню ниже того, что я пытаюсь изменить.
Я знаю, что логика внутри определения работает для вывода строки, которая мне нужна в качестве конечного результата, но доступ и замена их текущей логикой не работает.
Конечный результат должен выглядеть примерно так:
{
"12 November, 2020":
[
{
"id": "1",
"value": "1. Choice 1",
"checked": true
},
...
Вот как я в конечном итоге решил это.
json_data = json.loads(data)
dict_keys = json_data.keys()
timestamp = []
for x in dict_keys:
date_val = int(x) / 1000
dt_object = datetime.fromtimestamp(date_val)
date = dt_object.strftime("%B %d, %Y")
timestamp.append(date)
final_dict = dict(zip(timestamp, list(json_data.values())))
По сути, оказалось проще перетащить ключи в список, выполнить преобразование, а затем объединить этот список обратно в значения в качестве новых ключей вместо того, чтобы пытаться сделать это одним махом. Для тех, у кого строгие требования к производительности, это может быть не идеально, но для данного варианта использования это сработает.
Комментарии:
1. Я бы рекомендовал прочитать ericlippert.com/2014/03/05/how-to-debug-small-programs .
Ответ №1:
Вам гораздо лучше создавать новый dict
, чем возиться с ключами:
import json
from datetime import datetime
data_str = '''{
"1605855600000":
[
{ "id": "1", "value": "1. Choice 1", "checked": true },
{ "id": "2", "value": "2. Choice 2", "checked": false },
{ "id": "3", "value": "3. Choice 3", "checked": false },
{ "id": "4", "value": "4. Choice 4", "checked": false },
{ "id": "5", "value": "5. Choice 5", "checked": false }
],
"1604732400000":
[
{ "id": "1", "value": "1. Choice 1", "checked": false },
{ "id": "2", "value": "2. Choice 2", "checked": false },
{ "id": "3", "value": "3. Choice 3", "checked": false },
{ "id": "4", "value": "4. Choice 4", "checked": false },
{ "id": "5", "value": "5. Choice 5", "checked": false }
]
}'''
def convert_timestamp(key):
timestamp = int(key) / 1000
dt_object = datetime.fromtimestamp(timestamp)
return dt_object.strftime("%B %d, %Y")
def convert_keys(obj):
return {convert_timestamp(key):val for (key,val) in obj.items()}
data = json.loads(data_str)
new_data = convert_keys(data)
print(new_data)
Вывод:
{'November 20, 2020': [{'id': '1', 'value': '1. Choice 1', 'checked': True}, {'id': '2', 'value': '2. Choice 2', 'checked': False}, {'id': '3', 'value': '3. Choice 3', 'checked': False}, {'id': '4', 'value': '4. Choice 4', 'checked': False}, {'id': '5', 'value': '5. Choice 5', 'checked': False}], 'November 07, 2020': [{'id': '1', 'value': '1. Choice 1', 'checked': False}, {'id': '2', 'value': '2. Choice 2', 'checked': False}, {'id': '3', 'value': '3. Choice 3', 'checked': False}, {'id': '4', 'value': '4. Choice 4', 'checked': False}, {'id': '5', 'value': '5. Choice 5', 'checked': False}]}
Ответ №2:
Вы имели в виду:
data = json.loads(data)
data = convert_timestamp(data)
Комментарии:
1. Даже всякий раз, когда я конвертирую в это, он возвращает только первый преобразованный ключ, но не второй. Я пытался изменить структуру
return
в цикле for, но безуспешно.
Ответ №3:
Вы неправильно object_hook
использовали параметр json.loads
.
Из документов
object_hook — это необязательная функция, которая будет вызываться с результатом декодирования любого объектного литерала (dict). Вместо dict будет использоваться возвращаемое значение object_hook . Эта функция может быть использована для реализации пользовательских декодеров (например, подсказок класса JSON-RPC).
Следовательно, он принимает первый объект, найденный ключом. Как @quamrana упомянул в своем ответе, вам нужно сделать:
json_data = json.loads(data)
converted_data = convert_timestamp(json_data)
Кроме того, считается хорошей практикой не переопределять данные, а использовать отдельные переменные.
Комментарии:
1. Спасибо за разъяснение. Однако он по-прежнему возвращает только первое преобразуемое значение, как будто что-то не так в цикле, который не обращается ко всем значениям ключа.