2012-10-28 6 views
6

Ich bin ein JSON-Parser in C++ zu schreiben und ein Problem ist vor, wenn JSON-Strings Parsen:Wie behandelt man Unicode-Werte in JSON-Strings?

Die JSON-Spezifikation besagt, dass JSON-Strings Unicode-Zeichen in Form enthalten:

"here comes a unicode character: \u05d9 !" 

Meine JSON Parser versucht, JSON-Zeichenfolgen std::string zuzuordnen, so dass normalerweise ein Zeichen der JSON-Zeichenfolgen ein Zeichen der std::string wird. Doch für das Unicode-Zeichen, ich weiß wirklich nicht, was zu tun ist:

Soll ich nur das rohe Bytes Wert setzt in meinem std::string wie so:

std::string mystr; 
mystr.push_back('\0x05'); 
mystr.push_back('\0xd9'); 

Oder soll ich interpretiere die beiden Charaktere mit einem Bibliothek wie iconv und speichern Sie das UTF-8-codierte Ergebnis in meiner Zeichenfolge statt?

Sollte ich eine std::wstring verwenden, um alle Zeichen zu speichern? Was dann auf * NIX OSes wo wchar_t sind 4 Bytes lang?

Ich fühle, dass etwas in meinen Lösungen falsch ist, aber ich verstehe nicht was. Was soll ich in dieser Situation tun?

+0

Wenn wchar_t 4 Bytes lang ist, können Sie einfach Nullen erweitern ... UTF-8 bedeutet auch nicht 8-Bit-Zeichen. Nicht-ASCII wird mit mehreren Bytes in der UTF-8-Codierung gespeichert. –

+0

@ H2CO3: Sicher, in der Tat. http://json.org gibt an, dass eine * Zeichenkette * ** ein beliebiges UNICODE-Zeichen ** enthalten kann, aber es wird nicht angegeben, ob diese Zeichenketten UTF-8 oder UTF-16-kodiert sind. Es scheint mir, dass es UTF-8-Codierung mit einer speziellen Darstellung für UTF-16-Zeichen ist. Ein Ziel meiner Frage ist auch, das sicherzustellen. – ereOn

+3

gibt es keine "UTF-16-Zeichen". Es gibt Unicode-Zeichen, die nicht Teil von ASCII sind, und sie werden auch mit mehreren Bytes in UTF-8, UTF-16 und UTF-32 codiert. Die aus mehreren Bytes bestehenden Zeichenfolgen in UTF-16 und UTF-32 bestehen nur aus Bequemlichkeit, damit alle Zeichen die gleiche Länge haben. –

Antwort

11

Nach einigem Graben und dank H2CO3's comments und Philipp's comments, konnte ich endlich verstehen, wie das funktionieren soll:

die RFC4627, Abschnitt 3. Encoding Lesen:

  1. Codierung

    JSON-Text MUSS in Unicode codiert sein. Die Standardcodierung ist
    UTF-8.

    Da die ersten beiden Zeichen eines JSON Text immer ASCII sein Zeichen [RFC0020] ist es möglich, ob ein Oktett
    Strom UTF-8, um zu bestimmen, UTF-16 (BE oder LE) oder UTF -32 (BE oder LE), indem man
    nach dem Muster der Nullen in den ersten vier Oktetts sucht.

    00 00 00 xx UTF-32BE 
        00 xx 00 xx UTF-16BE 
        xx 00 00 00 UTF-32LE 
        xx 00 xx 00 UTF-16LE 
        xx xx xx xx UTF-8 
    

So scheint es, ein JSON Bytestrom in UTF-8 codiert werden kann, UTF-16 oder UTF-32 (sowohl in ihrer BE oder LE-Varianten, für die beiden letzten).

Sobald das klar ist, Section 2.5. Strings erklärt, wie diese \uXXXX Werte in JSON-Strings zu handhaben:

Jedes Zeichen maskiert werden kann. Wenn das Zeichen im Grunde
Multilingual Plane (U + 0000 bis U + FFFF) ist, dann kann es
seine als Sechszeichensequenz dargestellt wird: eine reversen Solidus, gefolgt
durch die Kleinbuchstabe u, gefolgt von vier hexadezimale Ziffern, die
den Codepunkt des Zeichens codieren. Die hexadezimalen Buchstaben A bis
F können Groß- oder Kleinbuchstaben sein. So kann beispielsweise eine Zeichenkette, die
nur ein einzelnes umgekehrtes Soliduszeichen enthält, als
"\ u005C" dargestellt werden.

Mit ausführlicheren Erklärungen für Zeichen nicht in der Basic Multilingual Plane.

ein erweitertes Zeichen zu entkommen, die nicht im Grundmehrsprachige Plane ist, wird das Zeichen als eine zwölfZeichenSequenz repräsentiert,
das UTF-16-Ersatzpaar codiert. So kann beispielsweise eine Zeichenkette
, die nur das G-Schlüsselzeichen (U + 1D11E) enthält, als
"\ uD834 \ uDD1E" dargestellt werden.

Hoffe das hilft.

+0

Hast du das zur Arbeit gebracht? Wenn ich meine wstring als L "{\" type \ ": \" string \ "," value \ ": \" \ u9CE5 \ "}, \ n", zeigt wcout \ u9CE5 für die Ausgabe in dieser Zeile . – Michele

2

Wenn ich Sie wäre, würde ich std :: string verwenden, um nur UTF-8 und UTF-8 zu speichern. Wenn ankommender JSON-Text keine \ uXXXX-Sequenzen enthält, kann std :: string unverändert Byte für Byte ohne Konvertierung verwendet werden.

Wenn Sie \ uXXXX parsen, können Sie es einfach dekodieren und in UTF-8 konvertieren, indem Sie es so behandeln, als wäre es ein wahres UTF-8-Zeichen - das tun die meisten JSON-Parser sowieso (libjson sicher). Wenn man JSON mit \ uXXXX liest und es sofort zurückschleudert, wenn man seine Bibliothek benutzt, verliert es wahrscheinlich die uXXXX-Sequenzen und ersetzt sie durch ihre echten UTF-8-Darstellungen, aber wen interessiert das wirklich? Letztendlich ist das Nettoergebnis immer noch genau gleich.

+0

Die Escape-Sequenzen bezeichnen UTF-16-Code-Einheiten, sodass Sie sie nicht einfach entschlüsseln können, ohne mindestens zwei Escape-Sequenzen zu betrachten. – Philipp

+0

@Philipp: so eine Schande auch ... sie waren sooo nah. –

Verwandte Themen