2012-03-06 15 views
15

Używam json.dump() i json.load() do zapisywania/odczytu słownika łańcuchów do/z dysku. Problem polega na tym, że nie mogę mieć żadnego z łańcuchów w Unicode. Wydaje się, że są w unicode, niezależnie od tego, jak ustawić parametry do zrzutu/ładowania (w tym zapewnienie_ascii i kodowania).Wymuszanie modułu json Python do pracy z ASCII

+5

proszę umieszczać swój rzeczywisty kod i wszelkie komunikaty o błędach otrzymujesz. Dziękuję Ci. – bernie

+0

Co masz na myśli przez "w Unicode"? Czy mówisz o ucieczce znaków spoza ASCII do "\ u1234"? Jeśli tak, dlaczego to kodowanie nie jest akceptowalne? Jest to całkowicie poprawny JSON, który każdy parser musi zaakceptować; istnieją znaki, które * muszą * być zakodowane w tym formacie, nawet jeśli generalnie pozostawiasz znaki nie-ASCII bez zmiany znaczenia. – bobince

+1

Ponieważ JSON natywnie jest w formacie utf-8. Json.loads() w języku Python akceptuje symbole inne niż ascii i przetwarza je na ciągi znaków Unicode. jsob.loads() przetwarza wszystkie łańcuchy znaków w typ "Pythona", a nie "str". Ale json.dumps() wymyka się ** wszystkim ** nie-ascii symboli! Tak, string! = Json.dumps (json.loads (string)) –

Odpowiedz

20

Jeśli jesteś po prostu do czynienia z prostych obiektów JSON, można użyć następujących:

def ascii_encode_dict(data): 
    ascii_encode = lambda x: x.encode('ascii') 
    return dict(map(ascii_encode, pair) for pair in data.items()) 

json.loads(json_data, object_hook=ascii_encode_dict) 

Oto przykład jak to działa:

>>> json_data = '{"foo": "bar", "bar": "baz"}' 
>>> json.loads(json_data)        # old call gives unicode 
{u'foo': u'bar', u'bar': u'baz'} 
>>> json.loads(json_data, object_hook=ascii_encode_dict) # new call gives str 
{'foo': 'bar', 'bar': 'baz'} 

This answer prace dla bardziej złożonych JSON strukturę i podaje kilka ładnych wyjaśnień na temat parametru object_hook. Istnieje również inna odpowiedź, która rekursywnie przyjmuje wynik wywołania json.loads() i konwertuje wszystkie ciągi znaków Unicode na ciągi bajtów.

+1

Możesz chcieć zmienić linię na 'ascii_encode = lambda x: x.encode ('ascii', 'ignore'), jeśli dane zawierają wiele znaków, których 'ord> 128'. – mac389

+0

Łącze do innej odpowiedzi dla bardziej złożonej struktury JSON było dokładnie tym, czego potrzebowałem. – adg

11

A jeśli obiekt JSON jest mieszanką typów danych nie tylko Unicode ciągi, można użyć tego wyrażenia:

def ascii_encode_dict(data): 
    ascii_encode = lambda x: x.encode('ascii') if isinstance(x, unicode) else x 
    return dict(map(ascii_encode, pair) for pair in data.items()) 
Powiązane problemy