2017-07-29 7 views
-1

Ich habe festgestellt, dass json.dumps immer den String in UTF-8 konvertiert, wie kann ich das verhindern? Sollte ich die Werte selbst codieren und dekodieren? Hier ist der Anwendungsfall, ich möchte, dass x ['a'] und y ['a'] identisch sind.Verhindern, dass json.dumps in Unicode konvertiert wird

x = {'a': '\xc3\xa6', 'b':u'æ', 'c':u'\xe6'} 
print type(x['a']), x 
<type 'str'> {'a': '\xc3\xa6', 'c': u'\xe6', 'b': u'\xe6'} 
t = json.dumps(x) 
print type(t),t 
<type 'str'> {"a": "\u00e6", "c": "\u00e6", "b": "\u00e6"} 
y = json.loads(t) 
print type(y['a']),y 
<type 'unicode'> {u'a': u'\xe6', u'c': u'\xe6', u'b': u'\xe6'} 
+0

JSON-Strings jedes Unicode-Zeichen darstellen kann, so Python 'unicode' Typ verwendet, ist die natürliche Wahl. Wenn Sie Bytes haben wollen (Python 2's 'str'), dann ist - laut dem Zen von Python - die Kodierung explizit besser, als sich auf eine implizite Zwangsumsetzung zu verlassen (wie es bei '' \ xc3 \ xa6'' im ersten Schritt der Fall ist)). – lenz

+0

Warum willst du "str" ​​haben? Wenn es nur das '' '- Präfix ist, das Sie ärgert, dann ist ein Upgrade auf Python 3 wahrscheinlich die beste Option. – lenz

+0

Wie möchten Sie, dass ''\ xc3 \ xa6'' trotzdem in JSON dargestellt wird? JSON verfügt nicht über einen Byte-Typ. Ihre Optionen dekodieren also oder konvertieren in ein Array mit Ganzzahlen. – lenz

Antwort

0

können Sie ein Objekt Haken definieren, der die Codierung für Sie tut:

>>> x = json.dumps({'a': u'\xe6', u'b': [1, 2, 3]}) 
>>> x 
'{"a": "\\u00e6", "b": [1, 2, 3]}' 
>>> json.loads(x, object_hook=no_unicode) 
{'a': '\xc3\xa6', 'b': [1, 2, 3]} 

Dieser Haken einfach codiert alle Schlüssel und Werte mit UTF-8 (wenn sie Strings):

def no_unicode(obj): 
    return {k.encode('utf8'): safe_encode(v) 
      for k, v in obj.iteritems()} 

def safe_encode(something): 
    if isinstance(something, unicode): 
     return something.encode('utf8') 
    return something 

Diese Lösung funktioniert jedoch nur für Strings, die direkte Mitglieder eines Objekts sind. Es wird nicht mehr funktionieren, wenn die Zeichenketten innerhalb einer Matrix/Liste verschachtelt sind:

>>> x = json.dumps({'a': [u'\xe6']}) 
>>> json.loads(x, object_hook=no_unicode) 
{'a': [u'\xe6']} 

oder wenn sie sich auf der obersten Ebene:

>>> x = json.dumps(u'\xe6') 
>>> json.loads(x, object_hook=no_unicode) 
u'\xe6' 

Der erste Fall kann durch die Verlängerung der Haken befestigt werden rekursiv in Container absteigen und versuchen, alle gefundenen Strings zu codieren. Allerdings kann ich keinen Weg finden, den zweiten Fall zu beheben. Die json bietet keine Hooks für andere Typen als Objekt (der Grund dafür könnte sein, dass ursprünglich die oberste Struktur eines JSON-Fragments ein Objekt sein musste).

+0

Ich habe gerade gemerkt, dass ich deine Frage nicht sorgfältig gelesen habe und du tatsächlich nach dem Gegenteil gefragt hast - was passiert in 'json.dumps', nicht' json.loads'. Diese Methode erfüllt jedoch immer noch Ihre Anforderung an 'x ['a']' und 'y ['a']' mit demselben Typ. – lenz

+0

Danke, ich war aufgeregt und hoffte, dass es etwas Ähnliches für json.dumps gab, stellt sich heraus, dass die Einstellung use_ascii = False auch nicht funktioniert. –

0

Konnte nicht herausfinden, eine andere Lösung, endete ich mit pickle, um bestimmte Teile meiner Datenstruktur zu serialisieren, die ich dann in der json Anfrage senden.

x = {'a': '\xc3\xa6', 'b':u'æ', 'c':u'\xe6'} 
t = pickle.dumps(x) 
t = base64.b64encode(t) 
print type(t),t 
y = pickle.loads(base64.b64decode(t)) 
print type(y['a']),y 

Diese richtig druckt:

<type 'str'> KGRwMApTJ2EnCnAxClMnXHhjM1x4YTYnCnAyCnNTJ2MnCnAzClbmCnA0CnNTJ2InCnA1Cmc0CnMu 
<type 'str'> {'a': '\xc3\xa6', 'c': u'\xe6', 'b': u'\xe6'} 
+0

Sicher, wenn es Python an beiden Enden ist, ist Beizen das natürliche Ding zu tun. – lenz

+0

Funktioniert für jetzt, aber ich wollte etwas, das auf lange Sicht breiter Unterstützung hätte. Ich hoffe immer noch, dass jemand etwas Licht ins Dunkel bringen kann. –

+0

Was braucht mehr Licht? Sie können nicht beides haben: Unterstützung für Pythons Datenmodell (= verschiedene Typen für 'str' und' bytes') und breite Unterstützung (= Unterstützung für Datenmodelle ohne diese Unterscheidung, zB JavaScript). – lenz

Verwandte Themen