Zuordnung zwischen JSON und XML

Die von der JsonReaderWriterFactory erzeugten Reader und Writer stellen eine XML API über JSON (JavaScript Object Notation)-Inhalte bereit. JSON codiert Daten mit einer Teilmenge der Objektliterale von JavaScript. Die von dieser Factory erzeugten Reader und Writer werden auch verwendet, wenn JSON-Inhalte von WCF-Anwendungen (Windows Communication Foundation) über WebMessageEncodingBindingElement oder WebHttpBinding gesendet oder empfangen werden.

Wenn der JSON-Reader mit JSON-Inhalten initialisiert wird, verhält er sich so wie ein XML-Reader bei XML-Inhalten. Wenn dem JSON-Writer eine Aufruffolge übergeben wird, die bei einem textbasierten XML-Reader eine bestimmte XML-Instanz erzeugt, wird JSON-Inhalt ausgegeben. Die Zuordnung zwischen dieser XML-Instanz und dem JSON-Inhalt wird in diesem Thema für die Verwendung in fortgeschrittenen Szenarios beschrieben.

Bei der Verarbeitung durch WCF wird JSON intern als XML-Infoset dargestellt. Normalerweise müssen Sie sich nicht mit dieser internen Darstellung befassen, da es sich lediglich um eine logische Zuordnung handelt: JSON wird normalerweise nicht im physischen Speicher in XML konvertiert bzw. XML wird nicht physisch in JSON umgewandelt. Diese Zuordnung bedeutet, dass über XML-APIs auf JSON-Inhalte zugegriffen wird.

Wenn JSON in WCF verwendet wird, wird im üblichen Szenario gegebenenfalls DataContractJsonSerializer automatisch vom WebScriptEnablingBehavior-Verhalten bzw. vom WebHttpBehavior-Verhalten eingebunden. Der DataContractJsonSerializer kennt die Zuordnung zwischen JSON und dem XML-Infoset und gibt vor, den JSON-Inhalt direkt zu verarbeiten. (Der DataContractJsonSerializer kann mit jedem beliebigen XML-Reader oder -Writer verwendet werden, sofern der XML-Inhalt der folgenden Zuordnung entspricht.)

In fortgeschrittenen Szenarios wird es möglicherweise notwendig, direkt auf die folgende Zuordnung zuzugreifen. Diese Szenarios sind gegeben, wenn Sie JSON mit einem benutzerdefinierten Verfahren serialisieren und deserialisieren möchten, ohne auf den DataContractJsonSerializer zurückzugreifen, oder wenn der Message-Typ bei Nachrichten, die JSON enthalten, direkt verarbeitet wird. Die JSON-XML-Zuordnung wird auch zur Nachrichtenprotokollierung verwendet. Bei Verwendung der Nachrichtenprotokollierungsfunktion in WCF werden JSON-Nachrichten entsprechend der im nächsten Abschnitt beschriebenen Zuordnung als XML protokolliert.

Das folgende Beispiel eines JSON-Dokuments soll zur Klärung dessZuordnungskonzepts dienen:

{"product":"pencil","price":12}

Um dieses JSON-Dokument mit einem der oben erwähnten Reader zu lesen, verwenden Sie die gleiche Sequenz von XmlDictionaryReader-Aufrufen, die Sie zum Lesen des folgenden XML-Dokuments verwenden würden:

<root type="object">
    <product type="string">pencil</product>
    <price type="number">12</price>
</root>

Wenn die JSON-Nachricht aus dem Beispiel von WCF empfangen und protokolliert wird, würde das vorstehende Protokoll außerdem das XML-Fragment enthalten.

Zuordnung zwischen JSON und dem XML-Infoset

Formal erfolgt die Zuordnung zwischen JSON gemäß RFC 4627 (wobei einige Einschränkungen gelockert und andere Einschränkungen hinzugefügt wurden) und dem XML-Infoset (nicht Text-XML) wie unter XML Information Set (XML-Infoset) beschrieben In diesem Thema finden Sie die Definitionen von Informationselementen und Feldern in [eckigen Klammern].

Ein leeres JSON-Dokument wird einem leeren XML-Dokument zugeordnet, und ein leeres XML-Dokument wird einem leeren JSON-Dokument zugeordnet. In der Zuordnung von XML zu JSON sind weder Leerräume vor noch Leerräume nach dem Dokument zulässig.

Die Zuordnung wird zwischen einem Dokumentinformationselement (Document Information Item, DII) oder einem Elementinformationselement (Element Information Item, EII) und JSON definiert. Das EII bzw. die [document element]-Eigenschaft des DII wird als JSON-Stammelement bezeichnet. Beachten Sie das, dass Dokumentfragmente (XML mit mehreren Stammelementen) nicht von dieser Zuordnung unterstützt werden.

Beispiel: Sowohl für das folgende Dokument:

<?xml version="1.0"?>
<root type="number">42</root>

als auch für das folgende Element:

<root type="number">42</root>

ist eine Zuordnung zu JSON definiert. Das <root>-Element stellt in beiden Fällen das JSON-Stammelement dar.

Weiterhin ist im Fall eines DII Folgendes zu berücksichtigen:

  • Einige Elemente dürfen in der [children]-Liste nicht vorhanden sein. Verlassen Sie sich beim Lesen von XML, das aus einer Zuordnung von JSON stammt, nicht auf diese Tatsache.

  • Die [children]-Liste enthält keine Kommentarinformationselemente.

  • Die [children]-Liste enthält keine DTD-Informationselemente.

  • Die [children]-Liste enthält keine Informationselemente mit personenbezogenen Informationen (PI). (Die Deklaration <?xml…> wird nicht als PI-Informationselement betrachtet.)

  • Der [notations]-Satz ist leer.

  • Der [unparsed entities]-Satz ist leer.

Beispiel: Das folgende Dokument kann JSON nicht zugeordnet werden, weil die [children]-Liste ein PI und einen Kommentar enthält.

<?xml version="1.0"?>
<!--comment--><?pi?>
<root type="number">42</root>

Das EII für das JSON-Stammelement verfügt über folgende Eigenschaften:

  • [local name] hat den Wert "root".

  • [namespace name] hat keinen Wert.

  • [prefix] hat keinen Wert.

  • [children] kann entweder EIIs (die innere Elemente darstellen, die an späterer Stelle näher beschrieben werden) oder CIIs (Character Information Items (Zeicheninformationselemente, die an späterer Stelle näher beschrieben werden) oder keines dieser Elemente enthalten, jedoch nicht beide Elementtypen.

  • [Attribute] kann die folgenden optionalen Attributinformationselemente (AIIs) enthalten.

  • Das JSON-Typattribut ("type"), das an späterer Stelle näher beschrieben wird. Dieses Attribut wird verwendet, um den JSON-Typ (String, Zahl, Boolean, Objekt, Array oder NULL) im zugeordneten XML beizubehalten.

  • Das Datenvertrags-Namensattribut ("__type"), das an späterer Stelle näher beschrieben wird. Dieses Attribut kann nur angegeben werden, wenn auch das JSON-Typattribut angegeben wurde und dessen [normalized value] gleich "object" ist. Dieses Attribut wird vom DataContractJsonSerializer verwendet, um die Typinformationen des Datenvertrags beizubehalten, beispielsweise in polymorphen Fällen, in denen ein abgeleiteter Typ serialisiert und ein Basistyp erwartet wird. Wenn Sie nicht mit dem DataContractJsonSerializer arbeiten, wird dieses Attribut wird meist ignoriert.

  • [in-scope namespaces] enthält die Bindung zwischen XML und http://www.w3.org/XML/1998/namespace entsprechend der Infosetspezifikation.

  • [children], [attributes] und [in-scope namespaces] dürfen keine anderen Elemente als die oben genannten enthalten, und [namespace attributes] darf keine Member enthalten. Sie dürfen sich beim Lesen von XML, das aus einer Zuordnung von JSON erzeugt wurde, aber nicht darauf verlassen, dass dies zutrifft.

Beispiel: Das folgende Dokument lässt sich JSON nicht zuordnen, weil [namespace attributes] nicht leer ist.

<?xml version="1.0"?>
<root xmlns:a="myattributevalue">42</root>

Das AII für das JSON-Typattribut verfügt über folgende Eigenschaften:

  • [namespace name] hat keinen Wert.
  • [prefix] hat keinen Wert.
  • [local name] lautet "type".
  • [normalized value] enthält einen der möglichen Typwerte, die im folgenden Abschnitt beschrieben werden.
  • [specified] hat den Wert true.
  • [attribute type] hat keinen Wert.
  • [references] hat keinen Wert.

Das AII für das Datenvertragsnamensattribut verfügt über folgende Eigenschaften:

  • [namespace name] hat keinen Wert.
  • [prefix] hat keinen Wert.
  • [local name] lautet "__type" (zwei Unterstriche und dann "type").
  • [normalized value] kann jede gültige Unicode-Zeichenfolge enthalten. Die Zuordnung dieser Zeichenfolge zu JSON wird im folgenden Abschnitt beschrieben.
  • [specified] hat den Wert true.
  • [attribute type] hat keinen Wert.
  • [references] hat keinen Wert.

Innere Elemente innerhalb des JSON-Stammelements oder andere innere Elemente verfügen über die folgenden Eigenschaften:

  • [local name] kann jeden beliebigen Wert enthalten, wie an späterer Stelle näher beschrieben wird.
  • Für [namespace name], [prefix], [children], [attributes], [namespace attributes] und [in-scope namespaces] gelten die gleichen Regeln wie für das JSON-Stammelement.

Sowohl im JSON-Stammelement als auch in den inneren Elementen definiert das JSON-Typattribut die Zuordnung zu JSON und den möglichen [children]-Elementen und deren Interpretation. Beim Element [normalized value] des Attributs wird die Groß- und Kleinschreibung beachtet. Es darf nur Kleinbuchstaben und keinen Leerraum enthalten.

[normalized value] des JSON-Typattributs „All“ Zulässige [children]-Elemente des entsprechenden EII Zuordnung zu JSON
string (oder Fehlen des JSON-Typs AII)

Ein string und das Fehlen des JSON- TypsAII sind gleichbedeutend, und somit ist string der Standard.

Deshalb wird <root> string1</root>string in JSON dem "string1" zugeordnet.
0 oder mehr CIIs Eine string in JSON (JSON RFC, Abschnitt 2.5). Jedes char ist ein Zeichen, das dem im CII angegebenen [character code] entspricht. Wenn keine CIIs vorhanden sind, wird eine leere JSON-string zugeordnet.

Beispiel: Das folgende Element wird einem JSON-Fragment zugeordnet.

<root type="string">42</root>

Das JSON-Fragment lautet "42".

Bei der Zuordnung von XML zu JSON müssen Zeichen, denen ein Escapezeichen vorangestellt werden muss, Escapezeichen zugeordnet werden. Alle anderen Zeichen werden Zeichen zugeordnet, denen keine Escapezeichen voransteht. Das Zeichen "/" ist ein Sonderfall. Ihm wird ein Escapezeichen vorangestellt, obwohl dies nicht notwendig ist (ausgeschrieben "\/").

Beispiel: Das folgende Element wird einem JSON-Fragment zugeordnet.

<root type="string">the "da/ta"</root>

Das JSON-Fragment lautet ""the \"da\/ta\"".

Bei der Zuordnung von JSON zu XML werden Zeichen, denen ein Escapezeichen vorangestellt ist, und andere Zeichen ohne Escapezeichen dem entsprechenden [character code] richtig zugeordnet.

Beispiel: Das JSON-Fragment "\u0041BC" entspricht dem folgenden XML-Element.

<root type="string">ABC</root>

Die Zeichenfolge kann in Leerräume („ws“ im Abschnitt 2 des JSON RFC) eingeschlossen werden, die nicht in XML dargestellt werden.

Beispiel: Das JSON-Fragment „ABC“ (es enthält Leerräume vor dem ersten Anführungszeichen) entspricht dem folgenden XML-Element:

<root type="string">ABC</root>

Jeder Leerraum in XML wird dem Leerraum in JSON zugeordnet.

Beispiel: Das folgende XML-Element wird einem JSON-Fragment zugeordnet.

<root type="string"> A BC </root>

Das JSON-Fragment lautet " A BC ".
number 1 oder mehr CIIs Ein JSON-number-Element (JSON RFC, Abschnitt 2.4), das von Leerraum umgeben sein kann. Jedes Zeichen in der Zahl-/Leerraum-Kombination ist ein Zeichen, das [character code] im CII entspricht.

Beispiel: Das folgende Element wird einem JSON-Fragment zugeordnet.

<root type="number"> 42</root>

Das JSON-Fragment lautet 42.

(Leerraum wird beibehalten.)
boolean 4 oder 5 CIIs (die true bzw. false entsprechen) und möglicherweise von weiteren Leerraum-CIIs umgeben sind. Eine CII-Folge, die der Zeichenfolge TRUE entspricht, wird dem Literal true zugeordnet, und eine CII-Folge, die der Zeichenfolge FALSE entspricht, wird dem Literal false zugeordnet. Die Zeichenfolge umgebende Leerräume werden beibehalten.

Beispiel: Das folgende Element wird einem JSON-Fragment zugeordnet.

<root type="boolean"> false</root>

Der JSON-Fragement lautet false.
null Keine Elemente zulässig. Das Literal null. Bei der Zuordnung von JSON zu XML kann null in Leerräume („ws“ im Abschnitt 2) eingeschlossen werden, die nicht in XML dargestellt werden.

Beispiel: Das folgende Element wird einem JSON-Fragment zugeordnet.

<root type="null"/>

oder

<root type="null"></root>

:

In beiden Fällen lautet das JSON-Fragement Null.
object 0 oder mehr EIIs. Eine begin-object (linke geschweifte Klammer) wie in Abschnitt 2.2 des JSON RFC definiert, gefolgt von einem Memberdatensatz für jedes EII, wie an späterer Stelle näher beschrieben wird. Wenn mehr als ein EII vorhanden ist, werden die Memberdatensätze durch Trennzeichen (Kommas) voneinander getrennt. Abgeschlossen wird die Angabe durch ein end-object (rechte geschweifte Klammer).

Beispiel: Das folgende Element wird dem JSON-Fragment zugeordnet.

<root type="object">

<type1 type="string">aaa\</type1>

<type2 type="string">bbb\</type2>

</root >

Der JSON-Fragement lautet {"type1":"aaa","type2":"bbb"}.

Wenn das Attribut für den Datenvertragstyp in der Zuordnung von XML zu JSON angegeben wird, dann wird am Anfang ein zusätzlicher Memberdatensatz hinzugefügt. Der Datensatz erhält als Namen das [local name]-Element des Datenvertragstypattributs ("__type") und als Wert das [normalized value]-Element des Attributs. Umgekehrt gilt für eine Zuordnung von JSON zu XML Folgendes: Wenn der Name des ersten Memberdatensatzes dem [local name]-Element des Datenvertragtypattributs entspricht (also gleich "__type" ist), dann enthält das zugeordnete XML ein Datenvertragtypattribut, es ist aber kein zugehöriges EII vorhanden. Beachten Sie, dass dieser Memberdatensatz als erster Datensatz im JSON-Objekt enthalten sein muss, damit diese spezielle Zuordnung erfolgen kann. Dies stellt eine Abweichung von der üblichen JSON-Verarbeitung dar, in der die Reihenfolge von Memberdatensätzen nicht von Bedeutung ist.

Beispiel:

Das folgende JSON-Fragment wird XML zugeordnet.

{"__type":"Person","name":"John"}

Der folgende Code stellt das XML dar:

<root type="object" __type="Person"> <name type="string">John</name> </root>

Beachten Sie, dass das AII __type, aber kein EII __type vorhanden ist.

Wenn die Reihenfolge in JSON umgekehrt wird, wie im folgenden Beispiel gezeigt,

{"name":"John","\_\_type":"Person"}

lautet das entsprechende XML wie folgt:

<root type="object"> <name type="string">John</name> <__type type="string">Person</__type> </root>

Das heißt, __type hat hier keine besondere Bedeutung mehr und wird wie üblich einem EII, keinem AII zugeordnet.

Für das [normalized value]-Element von AII gelten für die Verwendung von Escapezeichen bei der Zuordnung zu JSON-Werten die gleichen Regeln wie bei der Zuordnung zu JSON-Zeichenfolgen. Diese Regeln sind in der Zeile "string" dieser Tabelle angegeben.

Beispiel:

<root type="object" __type="\abc" />

aus dem vorigen Beispiel kann dem folgenden JSON zugeordnet werden.

{"__type":"\\abc"}

Bei einer Zuordnung von XML zu JSON darf das [local name]-Element eines EII nicht den Eintrag "__type" enthalten.

In der Zuordnung von Objekten von XML zu JSON wird kein Leerraum (ws) erzeugt, und bei der Zuordnung von JSON zu XML wird Leerraum ignoriert.

Beispiel: Das folgende JSON-Fragment wird einem XML-Element zugeordnet.

{ "ccc" : "aaa", "ddd" :"bbb"}

Das XML-Element wird im folgenden Code dargestellt.

<root type="object"> <ccc type="string">aaa</ccc> <ddd type="string">bbb</bar> </root >
array 0 oder mehr EIIs Ein begin-Array (linke eckige Klammer) entsprechend Abschnitt 2.3 des JSON RFC, gefolgt von einem Arraydatensatz für jedes EII, wie an späterer Stelle näher beschrieben wird. Wenn mehr als ein EII vorhanden ist, werden die Arraydatensätze durch Trennzeichen (Kommas) voneinander getrennt. Abgeschlossen wird dies durch ein end-Array.

Beispiel: Das folgende XML-Element wird einem JSON-Fragment zugeordnet.

<root type="array"/> <item type="string">aaa</item> <item type="string">bbb</item> </root >

Das JSON-Fragment lautet ["aaa","bbb"].

In der Zuordnung von Arrays von XML zu JSON wird kein Leerraum (ws) erzeugt, und bei der Zuordnung von JSON zu XML wird Leerraum ignoriert.

Beispiel: Ein JSON-Fragment.

["aaa", "bbb"]

Das XML-Element, das ihm zugeordnet wird.

<root type="array"/> <item type="string">aaa</item> <item type="string">bbb</item> </root >

Memberdatensätze werden wie folgt verarbeitet:

  • Das [local name]-Element des inneren Elements wird entsprechend Abschnitt 2.2 des JSON RFC dem string-Teil des member zugeordnet.

Beispiel: Das folgende Element wird einem JSON-Fragment zugeordnet.

<root type="object">
    <myLocalName type="string">aaa</myLocalName>
</root>

Das folgende JSON-Fragment wird angezeigt:

{"myLocalName":"aaa"}
  • Bei der Zuordnung von XML zu JSON müssen Zeichen, denen in JSON ein Escapezeichen vorangestellt werden muss, Escapezeichen zugeordnet werden. Alle anderen Zeichen werden Zeichen zugeordnet, denen kein Escapezeichen voransteht. Das Zeichen "/" ist ein Sonderfall. Ihm wird ein Escapezeichen vorangestellt, obwohl dies nicht notwendig ist. (Bei der Zuordnung von JSON zu XML muss ihm kein Escapezeichen vorangestellt werden.) Dies ist erforderlich, damit das ASP.NET AJAX-Format für DateTime-Daten in JSON unterstützt wird.

  • Bei einer Zuordnung von JSON zu XML werden alle Zeichen (einschließlich der Zeichen ohne Escapezeichen, falls erforderlich) zur Bildung eines string-Werts herangezogen, der ein [local name]-Element ergibt.

  • Innere Elemente [children] werden entsprechend dem JSON Type Attribute ebenso wie beim Root JSON Element dem Wert in Abschnitt 2.2 zugeordnet. Es sind mehrere Schachtelungsebenen von EIIs (einschließlich der Schachtelung innerhalb von Arrays) zulässig.

Beispiel: Das folgende Element wird einem JSON-Fragment zugeordnet.

<root type="object">
    <myLocalName1 type="string">myValue1</myLocalName1>
    <myLocalName2 type="number">2</myLocalName2>
    <myLocalName3 type="object">
        <myNestedName1 type="boolean">true</myNestedName1>
        <myNestedName2 type="null"/>
    </myLocalName3>
</root >

Das folgende JSON-Fragment resultiert aus dieser Zuordnung:

{"myLocalName1":"myValue1","myLocalName2":2,"myLocalName3":{"myNestedName1":true,"myNestedName2":null}}

Hinweis

Die vorangehende Zuordnung umfasst keinen XML-Codierungsschritt. Daher unterstützt WCF nur JSON-Dokumente, in denen Schlüsselnamen nur Zeichen enthalten, die auch in XML-Elementnamen zulässig sind. Beispielsweise wird das JSON-Dokument {"<":"a"} nicht unterstützt, weil < kein gültiger Name für ein XML-Element ist.

Der umgekehrte Fall (Zeichen, die in XML, aber nicht in JSON zulässig sind) stellt kein Problem dar, weil die vorangehende Zuordnung Schritte für das Voranstellen bzw. Entfernen von Escapezeichen in JSON beinhaltet.

Arraydatensätze werden wie folgt verarbeitet:

  • [local name] des inneren Elements lautet "item".

  • Das [children]-Element des inneren Elements wird entsprechend dem JSON-Attribut ebenso wie beim JSON-Stammelement dem Wert in Abschnitt 2.3 zugeordnet. Es sind mehrere Schachtelungsebenen von EIIs (einschließlich der Schachtelung innerhalb von Objekten) zulässig.

Beispiel: Das folgende Element wird einem JSON-Fragment zugeordnet.

<root type="array">
    <item type="string">myValue1</item>
    <item type="number">2</item>
    <item type="array">
    <item type="boolean">true</item>
    <item type="null"/></item>
</root>

Nachfolgend wird das JSON-Fragment dargestellt.

["myValue1",2,[true,null]]

Siehe auch