Mapování mezi JSON a XML
Čtenáři a zapisovači vytvořené prostřednictvím JsonReaderWriterFactory obsahu JSON (JavaScript Object Notation) poskytují rozhraní XML API. JSON kóduje data pomocí podmnožina literálů objektu JavaScriptu. Čtenáři a zapisovače vytvořené touto továrnou se používají také při odesílání nebo přijetí obsahu JSON aplikacemi Windows Communication Foundation (WCF) pomocí WebMessageEncodingBindingElement nebo WebHttpBinding.
Při inicializaci s obsahem JSON se čtečka JSON chová stejným způsobem jako textová čtečka XML v instanci XML. Zapisovač JSON při zadání posloupnosti volání, která v textové čtečce XML vytvoří určitou instanci XML, zapíše obsah JSON. Mapování mezi touto instancí XML a obsahem JSON je popsáno v tomto tématu pro použití v pokročilých scénářích.
Interně je JSON reprezentován jako informační sada XML při zpracování WCF. Obvykle se nemusíte zabývat tímto interním vyjádřením, protože mapování je pouze logické: JSON se obvykle fyzicky nepřevádí na XML v paměti nebo se převede na JSON z XML. Mapování znamená, že k přístupu k obsahu JSON se používají rozhraní API XML.
Když WCF používá JSON, obvyklým scénářem je, že DataContractJsonSerializer se automaticky připojí chováním WebScriptEnablingBehavior nebo chováním WebHttpBehavior , pokud je to vhodné. Rozumí DataContractJsonSerializer mapování mezi JSON a informační sadou XML a funguje, jako by se chytá přímo s JSON. (Je možné použít DataContractJsonSerializer s libovolným čtenářem NEBO zapisovačem XML s pochopením, že XML odpovídá následujícímu mapování.)
V pokročilých scénářích může být nutné získat přímý přístup k následujícímu mapování. K těmto scénářům dochází, když chcete serializovat a deserializovat JSON vlastními způsoby, aniž byste se museli spoléhat na typ DataContractJsonSerializernebo při práci s typem Message přímo pro zprávy obsahující JSON. Mapování JSON-XML se také používá k protokolování zpráv. Při použití funkce protokolování zpráv ve WCF se zprávy JSON protokolují jako XML podle mapování popsaného v další části.
Pro objasnění konceptu mapování je následující příklad dokumentu JSON.
{"product":"pencil","price":12}
Pokud chcete tento dokument JSON přečíst pomocí některého z dříve zmíněných XmlDictionaryReader čtenářů, použijte stejnou posloupnost volání, jakou byste si přečetli v následujícím dokumentu XML.
<root type="object">
<product type="string">pencil</product>
<price type="number">12</price>
</root>
Kromě toho pokud je zpráva JSON v příkladu přijata WCF a protokolována, zobrazí se fragment XML v předchozím protokolu.
Mapování mezi JSON a informační sadě XML
Formálně je mapování mezi JSON, jak je popsáno v dokumentu RFC 4627 (s výjimkou určitých omezení uvolněných a některých dalších omezení) a informační sady XML (a nikoli textové XML), jak je popsáno v sadě informací XML. V tomto tématu najdete definice položek informací a polí v [hranatých závorkách].
Prázdný dokument JSON se mapuje na prázdný dokument XML a prázdný dokument XML se mapuje na prázdný dokument JSON. V mapování XML na JSON nejsou povoleny předchozí prázdné znaky a koncové prázdné znaky po dokumentu.
Mapování je definováno mezi položkou informací o dokumentu (DII) nebo položkou informací o prvku (EII) a JSON. Vlastnost [element dokumentu] rozhraní DII nebo EII se označuje jako kořenový element JSON. Všimněte si, že v tomto mapování nejsou podporovány fragmenty dokumentů (XML s více kořenovými elementy).
Příklad: Následující dokument:
<?xml version="1.0"?>
<root type="number">42</root>
A následující prvek:
<root type="number">42</root>
Oba mají mapování na JSON. Element <root>
je kořenovým elementem JSON v obou případech.
V případě DII by se navíc mělo zvážit následující:
Některé položky v seznamu [podřízené] nesmí být přítomny. Při čtení XML namapovaného z JSON nespoléhejte na tento fakt.
Seznam [podřízené] neobsahuje žádné položky s informacemi o komentáři.
Seznam [podřízené] neobsahuje žádné položky informací DTD.
Seznam [podřízené] neobsahuje žádné osobní informace (PI) položky informací (
<?xml…>
deklarace není považována za položku informací o osobních údaji).Sada [notací] je prázdná.
Sada [neparsed entity] je prázdná.
Příklad: Následující dokument nemá žádné mapování na JSON, protože [podřízené] obsahuje PI a komentář.
<?xml version="1.0"?>
<!--comment--><?pi?>
<root type="number">42</root>
EII pro kořenový element JSON má následující vlastnosti:
[local name] má hodnotu root.
[název oboru názvů] nemá žádnou hodnotu.
[prefix] nemá žádnou hodnotu.
[podřízené] mohou obsahovat EII (které představují vnitřní prvky, jak je popsáno dále), nebo CII (položky informací o znakech, jak je popsáno dále) nebo žádné z nich, ale ne oba.
[atributy] mohou obsahovat následující volitelné položky informací o atributech (AII).
Atribut typu JSON ("type"), jak je popsáno dále. Tento atribut slouží k zachování typu JSON (řetězec, číslo, logická hodnota, objekt, pole nebo null) v mapovaném XML.
Atribut názvu kontraktu dat ("__type"), jak je popsáno dále. Tento atribut může být k dispozici pouze v případě, že je k dispozici atribut typu JSON a jeho [normalizovaná hodnota] je "object". Tento atribut se používá k zachování informací o typu kontraktu
DataContractJsonSerializer
dat , například v polymorfních případech, kdy je odvozený typ serializován a kde je očekáván základní typ. Pokud s tímto atributemDataContractJsonSerializer
nepracujete , ve většině případů se tento atribut ignoruje.[obory názvů v oboru] obsahují vazbu "xml" na
http://www.w3.org/XML/1998/namespace
pověření specifikace infosetu.[podřízené], [atributy] a [obory názvů v oboru] nesmí obsahovat žádné jiné položky než dříve zadané a [atributy oboru názvů] nesmí mít žádné členy, ale nespoléhejte na tato fakta při čtení XML namapovaného z JSON.
Příklad: Následující dokument nemá žádné mapování na JSON, protože [atributy oboru názvů] nejsou prázdné.
<?xml version="1.0"?>
<root xmlns:a="myattributevalue">42</root>
AII pro atribut typu JSON má následující charakteristiky:
- [název oboru názvů] nemá žádnou hodnotu.
- [prefix] nemá žádnou hodnotu.
- [local name] is "type".
- [normalizovaná hodnota] je jednou z možných hodnot typů popsaných v následující části.
- [zadané] je
true
. - [typ atributu] nemá žádnou hodnotu.
- [odkazy] nemají žádnou hodnotu.
Atribut AII pro název kontraktu dat má následující vlastnosti:
- [název oboru názvů] nemá žádnou hodnotu.
- [prefix] nemá žádnou hodnotu.
- [local name] is "__type" (dvě podtržítka a pak "type").
- [normalizovaná hodnota] je libovolný platný řetězec Unicode – mapování tohoto řetězce na JSON je popsáno v následující části.
- [zadané] je
true
. - [typ atributu] nemá žádnou hodnotu.
- [odkazy] nemají žádnou hodnotu.
Vnitřní prvky obsažené v kořenovém elementu JSON nebo jiných vnitřních prvcích mají následující charakteristiky:
- [local name] může mít libovolnou hodnotu, jak je popsáno dále.
- [název oboru názvů], [předpona], [podřízené], [atributy], [atributy oboru názvů] a [obory názvů v oboru] podléhají stejným pravidlům jako kořenový element JSON.
V kořenovém elementu JSON i vnitřních prvcích definuje atribut typu JSON mapování na JSON a možné [podřízené] a jejich interpretaci. [normalizovaná hodnota] atributu rozlišují malá a malá písmena a nesmí obsahovat prázdné znaky.
[normalizovaná hodnota] AII atributu typu JSON | Povoleno [podřízené] odpovídající EII | Mapování na JSON |
---|---|---|
string (nebo absence typu JSON AII)A string a absence AII typu JSON je stejná string jako výchozí.<root> string1</root> Proto se mapuje na řetězec JSON string "string1". |
0 nebo více CII | JSON (RFC JSON string , oddíl 2.5). Každý char je znak, který odpovídá [kódu znaku] z CII. Pokud neexistují žádné identifikátory CII, mapuje se na prázdný JSON string .Příklad: Následující prvek se mapuje na fragment JSON: <root type="string">42</root> Fragment JSON je 42. V mapování XML na JSON musí být znaky, které musí být řídicí mapovány na řídicí znaky, všechny ostatní mapují na znaky, které nejsou uchycené. Znak "/" je speciální – je řídicí znak, i když nemusí být (napsaný jako \/). Příklad: Následující prvek se mapuje na fragment JSON. <root type="string">the "da/ta"</root> Fragment JSON je "da\/ta\". V mapování JSON na XML se všechny řídicí znaky a znaky, které nejsou řídicími znaky správně mapovány na odpovídající [kód znaku]. Příklad: Fragment JSON \u0041BC se mapuje na následující element XML. <root type="string">ABC</root> Řetězec může být ohraničen prázdným znakem (ws v oddílu 2 dokumentu RFC JSON), který se nenamapuje na XML. Příklad: Fragment JSON "ABC" (před prvním dvojitým uvozovkou jsou mezery) se mapuje na následující element XML. <root type="string">ABC</root> Všechny prázdné znaky v XML se mapuje na prázdné znaky ve formátu JSON. Příklad: Následující element XML se mapuje na fragment JSON. <root type="string"> A BC </root> Fragment JSON je "A BC". |
number |
1 nebo více CII | JSON number (RFC JSON, oddíl 2.4) je pravděpodobně obklopen prázdným znakem. Každý znak v kombinaci s číslem nebo prázdným znakem je znak, který odpovídá [kódu znaku] z CII.Příklad: Následující prvek se mapuje na fragment JSON. <root type="number"> 42</root> Fragment JSON je 42. (Prázdné znaky se zachovají). |
boolean |
4 nebo 5 CII (které odpovídají true nebo false ) mohou být obklopeny dalšími prázdnými CII. |
Sekvence CII, která odpovídá řetězci "true", je namapována na literál true a sekvence CII, která odpovídá řetězci "false", je namapována na literál false . Okolní prázdné znaky se zachovají.Příklad: Následující prvek se mapuje na fragment JSON. <root type="boolean"> false</root> Fragment JSON je false . |
null |
Žádná není povolena. | Literál null . U mapování null JSON na XML může být prázdné znaky (ws v oddílu 2), které se nenamapují na XML.Příklad: Následující prvek se mapuje na fragment JSON. <root type="null"/> nebo <root type="null"></root> : Fragment JSON v obou případech je Null . |
object |
0 nebo více EII. | Složená begin-object složená závorka (vlevo) jako v části 2.2 dokumentu JSON RFC, za kterou následuje záznam člena pro každou EII, jak je popsáno dále. Pokud existuje více než jedna EII, mezi záznamy členů jsou oddělovače hodnot (čárky). Za tím vším následuje koncový objekt (pravá složená závorka).Příklad: Následující prvek se mapuje na fragment JSON. <root type="object"> <type1 type="string">aaa\</type1> <type2 type="string">bbb\</type2> </root > Fragment JSON je {"type1":"aaa","type2":"bbb"} .Pokud je atribut datového typu kontraktu k mapování XML na JSON, vloží se na začátek další záznam člena. Jeho název je [local name] atributu datového typu kontraktu ("__type") a jeho hodnota je [normalizovaná hodnota]. Naopak v mapování JSON na XML platí, že pokud je název prvního záznamu člena [místní název] atributu datového typu kontraktu (tj. "__type"), v mapovaném XML se nachází odpovídající atribut datového typu, ale odpovídající EII neexistuje. Všimněte si, že tento záznam člena musí nastat nejprve v objektu JSON, aby se toto speciální mapování použilo. Představuje odchod od obvyklého zpracování JSON, kdy pořadí záznamů členů není významné. Příklad: Následující fragment JSON se mapuje na XML. {"__type":"Person","name":"John"} Xml je následující kód. <root type="object" __type="Person"> <name type="string">John</name> </root> Všimněte si, že __type AII existuje, ale neexistuje žádná __type EII. Pokud je však pořadí ve formátu JSON obrácené, jak je znázorněno v následujícím příkladu. {"name":"John","\_\_type":"Person"} Zobrazí se odpovídající XML. <root type="object"> <name type="string">John</name> <__type type="string">Person</__type> </root> To znamená, že __type přestane mít zvláštní význam a mapuje se na EII jako obvykle, nikoli na AII. Pravidla pro zapouzdření/zrušení zapouzdření pro [normalizovanou hodnotu] AII při mapování na hodnotu JSON jsou stejná jako u řetězců JSON zadaných v řádku "string" této tabulky. Příklad: <root type="object" __type="\abc" /> na předchozí příklad lze namapovat na následující JSON. {"__type":"\\abc"} V mapování XML na JSON nesmí být první [místní název] EII "__type". Prázdné znaky ( ws ) se nikdy negenerují v mapování XML na JSON pro objekty a jsou ignorovány ve formátu JSON na mapování XML.Příklad: Následující fragment JSON se mapuje na element XML. { "ccc" : "aaa", "ddd" :"bbb"} Element XML je zobrazen v následujícím kódu. <root type="object"> <ccc type="string">aaa</ccc> <ddd type="string">bbb</bar> </root > |
pole | 0 nebo více EII | Počáteční pole (levá hranatá hranatá závorka) jako v části 2.3 dokumentu JSON RFC následované záznamem pole pro každou EII, jak je popsáno dále. Pokud existuje více než jedna EII, mezi záznamy pole jsou oddělovače hodnot (čárky). Za tím vším následuje koncové pole. Příklad: Následující element XML se mapuje na fragment JSON. <root type="array"/> <item type="string">aaa</item> <item type="string">bbb</item> </root > Fragment JSON je ["aaa","bbb"] Prázdné znaky ( ws ) se nikdy negenerují v mapování XML na JSON pro pole a v mapování JSON na XML se ignorují.Příklad: Fragment JSON. ["aaa", "bbb"] Element XML, na který se mapuje. <root type="array"/> <item type="string">aaa</item> <item type="string">bbb</item> </root > |
Záznamy členů fungují takto:
- Vnitřní element [local name] se mapuje na
string
částmember
definovanou v oddílu 2.2 dokumentu RFC JSON.
Příklad: Následující prvek se mapuje na fragment JSON.
<root type="object">
<myLocalName type="string">aaa</myLocalName>
</root>
Zobrazí se následující fragment JSON.
{"myLocalName":"aaa"}
V mapování XML na JSON se znaky, které musí být v kódu JSON uchycené, uchytnou a ostatní neuniknou. Znak "/", i když není znakem, který musí být řídicí, je však řídicí znak (nemusí být ucháznut do mapování JSON na XML). To se vyžaduje pro podporu formátu ASP.NET AJAX pro
DateTime
data ve formátu JSON.V mapování JSON na XML se všechny znaky (včetně bez řídicích znaků v případě potřeby) převedou tak, aby vytvořily
string
[místní název].Vnitřní prvky [podřízené] se mapuje na hodnotu v oddílu
Root JSON Element
2.2 podleJSON Type Attribute
toho, jak je tomu u . Je povoleno více úrovní vnoření EII (včetně vnoření v polích).
Příklad: Následující prvek se mapuje na fragment JSON.
<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 >
Následující fragment JSON je to, na co se mapuje.
{"myLocalName1":"myValue1","myLocalName2":2,"myLocalName3":{"myNestedName1":true,"myNestedName2":null}}
Poznámka:
V předchozím mapování neexistuje žádný krok kódování XML. WCF proto podporuje pouze dokumenty JSON, ve kterých jsou všechny znaky v názvech klíčů platné znaky v názvech elementů XML. Například dokument JSON {"<:"a"} není podporován, protože < není platný název elementu XML.
Obrácená situace (znaky platné ve formátu XML, ale ne ve formátu JSON) nezpůsobuje žádné problémy, protože předchozí mapování zahrnuje zapouzdření nebo zrušení zapouzdření kódu JSON.
Záznamy polí fungují takto:
Vnitřní prvek [local name] je "item".
Vnitřní element [podřízené] se mapuje na hodnotu v oddílu 2.3 podle atributu typu JSON stejně jako u kořenového elementu JSON. Je povoleno více úrovní vnoření EII (včetně vnoření v rámci objektů).
Příklad: Následující prvek se mapuje na fragment JSON.
<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>
Následuje fragment JSON.
["myValue1",2,[true,null]]