Преобразование строкового представления словаря со значениями даты и времени обратно в словарь

1

У меня есть строковое представление словаря. Это вложенный словарь, еще более сложный, из которого ключ record_time имеет значение datetime, как record_time ниже:

d = """{
    "motion_measure": {"INCAR": 69, "RANDOM": 63, "UNKNOWN": 62, "BIKING": 57, "WALKING": 48, "RUNNING": 41, "SEDENTARY": 0},
    "samples": [0, 1.1791444, 11.036073],
    "record_time": datetime.datetime(2018, 3, 26, 10, 3, 17, 441000)
    }"""

Я попробовал два метода, предложенных в этом связанном вопросе:

import ast

ast.literal_eval(d)

ast.literal_eval не работает, потому что он не может обрабатывать значение datetime.

import json

json.loads(d) 

json.loads не работает либо потому, что формат datetime не десериализуем.

Кто-нибудь знает хороший способ конвертировать его обратно в dict или json с помощью Python? Я получил этот странный формат записи от OrientDB.

Теги:
string
datetime
dictionary

2 ответа

0

Поскольку ваша строка почти json, вы можете просто немного ее очистить и использовать json.loads (и избегать eval).

Например, если вы согласны с преобразованием значений даты и времени в списки, то одним из способов было бы заменить все экземпляры datetime.datetime(...) в вашей строке перед преобразованием в dict (в примере ниже используется regex для обработки замена). Затем вы можете использовать datetime для работы с списками datetime в результирующем dict.

Например (добавлено дополнительное datetime к вашей входной строке, чтобы гарантировать, что замена обрабатывает множественные вхождения даты и времени без заданных миллисекунд и т.д.):

import datetime
import re
import json

s = """{
    "motion_measure": {"INCAR": 69, "RANDOM": 63, "UNKNOWN": 62, "BIKING": 57, "WALKING": 48, "RUNNING": 41, "SEDENTARY": 0},
    "samples": [0, 1.1791444, 11.036073],
    "record_time": datetime.datetime(2018, 3, 26, 10, 3, 17, 441000), 
    "another_time": datetime.datetime(2017, 3, 26, 10, 3)
    }"""

# re.sub to replace datetime; json.loads to convert to dict
d = json.loads(re.sub(r'datetime\.datetime\(([^)]*)\)', r'[\1]', s))

# datetime.datetime(...) to work with resulting datetime lists
date1 = datetime.datetime(*d['record_time'])
date2 = datetime.datetime(*d['another_time'])

print(d)
# OUTPUT (shown on multiple lines for readability)
# {
# 'motion_measure': {'INCAR': 69, 'RANDOM': 63, 'UNKNOWN': 62, 'BIKING': 57, 'WALKING': 48, 'RUNNING': 41, 'SEDENTARY': 0},
# 'samples': [0, 1.1791444, 11.036073],
# 'record_time': [2018, 3, 26, 10, 3, 17, 441000],
# 'another_time': [2017, 3, 26, 10, 3]
# }

print(date1)
print(date2)
# OUTPUT
# 2018-03-26 10:03:17.441000
# 2017-03-26 10:03:00
  • 0
    здорово! Спасибо за ответ! Я также думаю о замене всех datetime на кавычки, чтобы я мог продолжить, используя метод json.loads. Но я застрял с регулярным выражением, не могли бы вы немного объяснить, как работает магия регулярного выражения? @benvc
  • 0
    @ericR - re.sub использует регулярные выражения для замены строк. datetime\.datetime\( бит соответствует «datetime.datetime (» (обратные слэши экранируют специальные символы в регулярном выражении). Бит ([^)]*) соответствует «группе захвата» (получая значения, которые мы хотим для замены строки ) - заключенная в скобки часть представляет собой набор символов с отрицанием, за которым следует звездочка, указывающая, что нужно захватить все до закрывающей скобки. Последний бит \) соответствует последней закрывающей скобке. Параметр r'"\1"' указывает re.sub заменить строку, сопоставленную с регулярным выражением, на первую (и единственную) группу захвата, которую мы сопоставили.
Показать ещё 4 комментария
0

Если вы используете "eval" (это опасно, поскольку он выполняет данные.), Вы можете просто "eval".

import datetime
d = <... your string ...>
new_dict = eval(d)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню