2015-06-15 18 views
5

Używam Pythona do kodować OrderedDict ze znacznikiem czasu w nim i mam problemy. Dane, które próbuję zakodować wygląda następująco:python - za pomocą JSON z OrderedDict i Datetime

OrderedDict([('a', datetime.datetime(2015, 6, 15, 15, 58, 54, 884000)), ('b', 'b'), ('c', 'c'), ('d', 'd')]) 

Spodziewam to być json kodowane i dekodowane, aby uzyskać dokładnie te same dane.

W celu zakodowania timestamp bezpośrednio, bez zmiany ISO lub Unix raz użyłem interfejsu json_util bson jako poniżej. Działa poprawnie.

json.dumps(str, default=json_util.default) 
json.loads(jsonstr, object_hook=json_util.object_hook) 

W celu uzyskania OrderedDict użyłem object_pairs_hook, który działa również:

json.loads(x, object_pairs_hook=OrderedDict) 

Jednak, gdy stosowane razem, bałagan dwie rzeczy ze sobą, a wynik nie jest w prawidłowym formacie (Ponieważ interfejs bson tworzy dodatkowy słownik dla znacznika czasu).

json.loads(jsonstr, object_hook=json_util.object_hook, object_pairs_hook=OrderedDict) 

To zapytanie kończy się coraz to:

OrderedDict([(u'a', OrderedDict([(u'$date', 1434383934884L)])), (u'b', u'b'), (u'c', u'c'), (u'd', u'd')]) 

Znacznik czasu nie jest analizowany poprawnie. Wszelkie sugestie, jak to zrobić poprawnie? (Pickle może być kierunkiem, ale najpierw szukam innych rozwiązań).

+0

co robi '' json_util.object_hook'' wyjście '' datetime'' obiektów? –

+0

@JamesMills to wyjście '{"a": {"$ date": 1434383934884}, "b": "b", "c": "c", "d": "d"} ". Ten dodatkowy słownik jest parsowany jako OrderDict przez object_pairs_hook tym samym zatrzymując object_hook, aby go zdekodować. –

+0

Jest zakodowany jako znacznik UNIX jako '' {"$ date": ""} ''? –

Odpowiedz

2

Można zdefiniować własny dekoder, który będzie obsługiwać zarówno datetime i OrderedDict i używać go w object_pairs_hook. Dla wygody i testowania zdefiniowałem także mój własny koder, ale możesz korzystać z tego, który już posiadasz.

#!/usr/bin/env python3 

import json 
import datetime 
from collections import OrderedDict 

# Test dictionary 
a = OrderedDict([('a', datetime.datetime(2015, 6, 15, 15, 58, 54, 884000)), 
       ('b', 'b'), ('c', 'c'), ('d', 'd')]) 
print(a) 

# Encoder for datetime 
def encoder(obj): 
    if type(obj) is datetime.datetime: 
     return {'$date$': obj.timestamp()} 
    raise TypeError 

# Encode 
s = json.dumps(a, default=encoder) 
print("JSON:", s) 

# Decoder for OrderedDict and datetime 
def decoder(obj): 
    if len(obj) == 1 and len(obj[0]) == 2 and obj[0][0] == '$date$': 
     return datetime.datetime.fromtimestamp(obj[0][1]) 
    else: 
     return OrderedDict(obj) 

# Decode 
b = json.loads(s, object_pairs_hook=decoder) 
print(b) 

# Compare 
print("Comparing:", a == b) 

ten wypisze:

OrderedDict([('a', datetime.datetime(2015, 6, 15, 15, 58, 54, 884000)), ('b', 'b'), ('c', 'c'), ('d', 'd')]) 
JSON: {"a": {"$date$": 1434409134.884}, "b": "b", "c": "c", "d": "d"} 
OrderedDict([('a', datetime.datetime(2015, 6, 15, 15, 58, 54, 884000)), ('b', 'b'), ('c', 'c'), ('d', 'd')]) 
Comparing: True 
+0

Awesome, thanks. Nie myślałem przez ten utwór. –

1

Dlaczego nie można zakodować/odkodować obiekt datetime bezpośrednio?

import datetime as dt 
import json 
from collections import OrderedDict 

datetime_encoding = '%Y-%m-%d %H:%M.%S %f' 

od = OrderedDict([('a', dt.datetime(2015, 6, 15, 15, 58, 54, 884000).strftime(datetime_encoding)), ('b', 'b'), ('c', 'c'), ('d', 'd')]) 

x = json.dumps(od) 

od_new = json.loads(x) 
od_new['a'] = dt.datetime.strptime(od_new['a'], datetime_encoding) 

>>> od_new 
{u'a': datetime.datetime(2015, 6, 15, 15, 58, 54, 884000), 
u'b': u'b', 
u'c': u'c', 
u'd': u'd'} 
+1

Dzięki za odpowiedź. W rzeczywistości jest to bardzo duży słownik python z zagnieżdżonym słownikiem i zagnieżdżonym znacznikiem czasu. Próbuję uniknąć ręcznego przechodzenia przez dane i zmieniania datetime. A następnie przetestuj ponownie podczas dekodowania, aby zmienić to z powrotem. –

+0

Pomyślałem, że może tak być ... – Alexander

+0

Tak, wszyscy mamy nadzieję, że życie jest tak proste jak powyższy przykład. :) –

Powiązane problemy