2015-06-15 18 views
5

Ben bir zaman damgası ile bir OrderedDict kodlamak için python kullanıyorum ve sorunları yaşıyorum. Ben kodlamak çalışıyorum veri şuna benzer: python - OrderedDict ve Datetime ile json kullanarak

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

bu json kodlanmış ve tam olarak aynı verileri almak için deşifre olmasını bekliyoruz.

Zaman damgasını doğrudan ISO veya Unix zamanına değiştirmeden kodlamak için, aşağıdaki gibi bson json_util arayüzünü kullandım. Doğru çalışıyor. da çalışır ben object_pairs_hook kullanılan bir OrderedDict, alabilmek için

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

:

json.loads(x, object_pairs_hook=OrderedDict) 

Ancak birlikte kullanıldıklarında, birbirleriyle ve sonuçla iki şey karmaşa doğru biçimde değil (Bson arayüzü zaman damgası için ekstra bir sözlük oluşturduğundan).

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

Bu sorgu, bu elde biter:

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

damgası doğru dışarı değil ayrıştırılır. Bunu nasıl doğru yapacağınıza dair herhangi bir öneriniz var mı? (Turşu bir yön olabilir ama önce başka çözümler arıyorum).

+0

ne yapar '' json_util.object_hook'' çıktı? –

+0

@JamesMills çıkışını '{"a": {"$ date": 1434383934884}, "b": "b", "c": "c", "d": "d"}'. Bu ekstra sözlük, object_pairs_hook tarafından OrderDict olarak ayrıştırıldı, böylece decode etmek için object_hook durdu. –

+0

Yani UNIX Zaman Damgası olarak "' {"$ date" olarak kodlandı: ""} ''? –

cevap

2

Hem datetime ve OrderedDict işlemek ve object_pairs_hook bunu kullanacak kendi dekoder tanımlayabilirsiniz. Kolaylık ve test için kendi kodlayıcımı da tanımladım, ancak zaten sahip olduğunuzı kullanmakta özgürsünüz.

#!/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) 

Bu yazdırır: `` datetime`` nesneler için

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

Harika, teşekkürler. Bu yol boyunca düşünmedim. –

1

Neden datetime nesnesini doğrudan kodlamıyor/çözemiyorsunuz?

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

Yanıt için teşekkürler. Gerçekte, iç içe geçmiş sözlüğe ve iç içe geçmiş zaman damgasına sahip çok büyük bir python sözlüğü. Veriler arasında manuel olarak geçiş yapmaktan kaçınıyorum ve tarih saatini kendim değiştiriyorum. Ve sonra bunu değiştirmek için kod çözerken tekrar hareket ettirin. –

+0

Durumun böyle olabileceğini düşündüm ... – Alexander

+0

Evet, hepimiz hayatın yukarıdaki örnek kadar kolay olduğunu umuyoruz. :) –