Dela via


Mappning mellan JSON och XML

Läsare och författare som skapats av JsonReaderWriterFactory tillhandahåller ett XML-API över JSON-innehåll (JavaScript Object Notation). JSON kodar data med hjälp av en delmängd av objektliteralerna i JavaScript. Läsare och författare som produceras av den här fabriken används också när JSON-innehåll skickas eller tas emot av WCF-program (Windows Communication Foundation) med hjälp WebMessageEncodingBindingElement av eller WebHttpBinding.

När JSON-läsaren initieras med JSON-innehåll fungerar den på samma sätt som en textbaserad XML-läsare gör över en instans av XML. JSON-skrivaren skriver ut JSON-innehåll när den får en sekvens med anrop som på en textbaserad XML-läsare genererar en viss XML-instans. Mappningen mellan den här instansen av XML och JSON-innehållet beskrivs i det här avsnittet för användning i avancerade scenarier.

Internt representeras JSON som en XML-informationsuppsättning när den bearbetas av WCF. Normalt behöver du inte bry dig om den här interna representationen eftersom mappningen bara är logisk: JSON konverteras normalt inte fysiskt till XML i minnet eller konverteras till JSON från XML. Mappningen innebär att XML-API:er används för att komma åt JSON-innehåll.

När WCF använder JSON är det vanliga scenariot att DataContractJsonSerializer automatiskt ansluts av WebScriptEnablingBehavior beteendet eller av beteendet när det WebHttpBehavior är lämpligt. Förstår DataContractJsonSerializer mappningen mellan JSON och XML-informationsuppsättningen och fungerar som om den hanterar JSON direkt. (Det är möjligt att använda DataContractJsonSerializer med valfri XML-läsare eller -skrivare, med förståelsen att XML:en överensstämmer med följande mappning.)

I avancerade scenarier kan det bli nödvändigt att komma åt följande mappning direkt. Dessa scenarier inträffar när du vill serialisera och deserialisera JSON på anpassade sätt, utan att förlita dig på DataContractJsonSerializer, eller när du hanterar Message typen direkt för meddelanden som innehåller JSON. JSON-XML-mappningen används också för meddelandeloggning. När du använder funktionen för meddelandeloggning i WCF loggas JSON-meddelanden som XML enligt mappningen som beskrivs i nästa avsnitt.

För att förtydliga begreppet mappning är följande exempel på ett JSON-dokument.

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

Om du vill läsa det här JSON-dokumentet med någon av de läsare som tidigare nämnts använder du samma anropssekvens XmlDictionaryReader som du skulle göra för att läsa följande XML-dokument.

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

Om JSON-meddelandet i exemplet tas emot av WCF och loggas ser du dessutom XML-fragmentet i föregående logg.

Mappning mellan JSON och XML-informationsuppsättningen

Formellt sett är mappningen mellan JSON enligt beskrivningen i RFC 4627 (förutom med vissa begränsningar som är begränsade och vissa andra begränsningar har lagts till) och XML-informationsuppsättningen (och inte textbaserad XML) enligt beskrivningen i XML-informationsuppsättningen. Se det här avsnittet för definitioner av informationsobjekt och fält i [hakparenteser].

Ett tomt JSON-dokument mappar till ett tomt XML-dokument och ett tomt XML-dokument mappar till ett tomt JSON-dokument. I XML-till-JSON-mappningen tillåts inte föregående blanksteg och avslutande tomt utrymme efter dokumentet.

Mappningen definieras mellan antingen ett dokumentinformationsobjekt (DII) eller ett elementinformationsobjekt (EII) och JSON. Egenskapen EII, eller DII:ns [dokumentelement] kallas för rot-JSON-elementet. Observera att dokumentfragment (XML med flera rotelement) inte stöds i den här mappningen.

Exempel: Följande dokument:

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

Och följande element:

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

Båda har en mappning till JSON. Elementet <root> är rot-JSON-elementet i båda fallen.

När det gäller dii bör följande beaktas:

  • Vissa objekt i listan [underordnade] får inte finnas. Förlita dig inte på det här faktumet när du läser XML som mappats från JSON.

  • Listan [underordnade] innehåller inga kommentarsinformationsobjekt.

  • Listan [underordnade] innehåller inga DTD-informationsobjekt.

  • Listan [underordnade] innehåller inga informationsobjekt för personlig information (PI) (deklarationen <?xml…> betraktas inte som ett PI-informationsobjekt)

  • Uppsättningen [notationer] är tom.

  • Uppsättningen [oparerade entiteter] är tom.

Exempel: Följande dokument har ingen mappning till JSON eftersom [underordnade] innehåller en PI och en kommentar.

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

EII för rot-JSON-elementet har följande egenskaper:

  • [lokalt namn] har värdet "root".

  • [namnområdesnamn] har inget värde.

  • [prefix] har inget värde.

  • [underordnade] kan antingen innehålla EIIs (som representerar inre element enligt beskrivningen ytterligare) eller CIIs (teckeninformationsobjekt enligt beskrivningen ytterligare) eller inget av dessa, men inte båda.

  • [attribut] kan innehålla följande valfria attributinformationsobjekt (AIIs)

  • JSON-typattributet ("typ") enligt beskrivningen ytterligare. Det här attributet används för att bevara JSON-typen (sträng, nummer, booleskt värde, objekt, matris eller null) i den mappade XML-koden.

  • Datakontraktets namnattribut ("__type") enligt beskrivningen ytterligare. Det här attributet kan bara finnas om JSON-typattributet också finns och dess [normaliserade värde] är "objekt". Det här attributet används av DataContractJsonSerializer för att bevara information om datakontraktstyp, till exempel i polymorfa fall där en härledd typ serialiseras och där en bastyp förväntas. Om du inte arbetar med DataContractJsonSerializeri de flesta fall ignoreras det här attributet.

  • [namnområden i omfånget] innehåller bindningen av "xml" till http://www.w3.org/XML/1998/namespace enligt infouppsättningsspecifikationen.

  • [underordnade], [attribut] och [namnområden i omfånget] får inte ha några andra objekt än vad som angavs tidigare och [namnområdesattribut] får inte ha några medlemmar, men förlita dig inte på dessa fakta när du läser XML som mappats från JSON.

Exempel: Följande dokument har ingen mappning till JSON eftersom [namnområdesattribut] inte är tomt.

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

AII för JSON-typattributet har följande egenskaper:

  • [namnområdesnamn] har inget värde.
  • [prefix] har inget värde.
  • [lokalt namn] är "type".
  • [normaliserat värde] är ett av de möjliga typvärden som beskrivs i följande avsnitt.
  • [angiven] är true.
  • [attributtyp] har inget värde.
  • [referenser] har inget värde.

Attributet AII för datakontraktets namn har följande egenskaper:

  • [namnområdesnamn] har inget värde.
  • [prefix] har inget värde.
  • [lokalt namn] är "__type" (två understreck och sedan "typ").
  • [normaliserat värde] är en giltig Unicode-sträng – mappningen av strängen till JSON beskrivs i följande avsnitt.
  • [angiven] är true.
  • [attributtyp] har inget värde.
  • [referenser] har inget värde.

Inre element i rot-JSON-elementet eller andra inre element har följande egenskaper:

  • [lokalt namn] kan ha valfritt värde enligt beskrivningen ytterligare.
  • [namnområdesnamn], [prefix], [underordnade], [attribut], [namnområdesattribut] och [namnområden i omfånget] omfattas av samma regler som rot-JSON-elementet.

I både rot-JSON-elementet och de inre elementen definierar JSON-typattributet mappningen till JSON och möjliga [underordnade] och deras tolkning. Attributets [normaliserade värde] är skiftlägeskänsligt och måste vara gemener och får inte innehålla tomt utrymme.

[normaliserat värde] för JSON-typattributets AII Tillåtna [underordnade] av motsvarande EII Mappning till JSON
string (eller avsaknad av JSON-typen AII)

A string och frånvaron av JSON-typen AII är samma gör string standardvärdet.

<root> string1</root> Så mappar till JSON string "string1".
0 eller fler CII:er En JSON string (JSON RFC, avsnitt 2.5). Var och char en är ett tecken som motsvarar [teckenkoden] från CII. Om det inte finns några CII:er mappas det till en tom JSON string.

Exempel: Följande element mappar till ett JSON-fragment:

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

JSON-fragmentet är "42".

I XML till JSON-mappning mappar tecken som måste vara undantagna till undantagna tecken, alla andra mappar till tecken som inte är undantagna. Tecknet "/" är speciellt – det är undantaget även om det inte behöver vara (skrivs ut som "\/").

Exempel: Följande element mappar till ett JSON-fragment.

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

JSON-fragmentet är "da\/ta\".

Vid JSON till XML-mappning mappas alla undantagna tecken och tecken som inte är undantagna mappas korrekt till motsvarande [teckenkod].

Exempel: JSON-fragmentet "\u0041BC" mappar till följande XML-element.

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

Strängen kan omges av blanksteg ("ws" i avsnitt 2 i JSON RFC) som inte mappas till XML.

Exempel: JSON-fragmentet "ABC", (det finns blanksteg före det första dubbla citatt) mappar till följande XML-element.

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

Tomt utrymme i XML mappar till tomt utrymme i JSON.

Exempel: Följande XML-element mappar till ett JSON-fragment.

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

JSON-fragmentet är " A BC ".
number 1 eller fler CII:er En JSON number (JSON RFC, avsnitt 2.4), eventuellt omgiven av tomt utrymme. Varje tecken i kombinationen tal/tomt utrymme är ett tecken som motsvarar [teckenkoden] från CII.

Exempel: Följande element mappar till ett JSON-fragment.

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

JSON-fragmentet är 42

(Tomt utrymme bevaras).
boolean 4 eller 5 CII:er (som motsvarar true eller false), eventuellt omgivna av ytterligare URI:er för blanksteg. En CII-sekvens som motsvarar strängen "true" mappas till literalen trueoch en CII-sekvens som motsvarar strängen "false" mappas till literalen false. Omgivande tomt utrymme bevaras.

Exempel: Följande element mappar till ett JSON-fragment.

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

JSON-fragmentet är false.
null Ingen tillåts. Literalen null. Vid JSON till XML-mappning null kan det vara omgivet av tomt utrymme ("ws" i avsnitt 2) som inte mappas till XML.

Exempel: Följande element mappar till ett JSON-fragment.

<root type="null"/>

eller

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

:

JSON-fragmentet i båda fallen är Null.
object 0 eller fler EIC:er. A begin-object (vänster klammerparentes) som i avsnitt 2.2 i JSON RFC, följt av en medlemspost för varje EII enligt beskrivningen vidare. Om det finns fler än en EII finns det värdeavgränsare (kommatecken) mellan medlemsposterna. Allt detta följs av ett slutobjekt (höger klammerparentes).

Exempel: Följande element mappar till JSON-fragmentet.

<root type="object">

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

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

</root >

JSON-fragmentet är {"type1":"aaa","type2":"bbb"}.

Om attributet Data Contract Type finns i XML till JSON-mappning infogas ytterligare en medlemspost i början. Dess namn är [lokalt namn] för attributet Data Contract Type ("__type"), och dess värde är attributets [normaliserade värde]. Om den första medlemspostens namn på JSON till XML-mappning däremot är [lokalt namn] för attributet datakontraktstyp (d.v.s. "__type" finns ett motsvarande datakontraktstypattribut i den mappade XML-koden, men motsvarande EII finns inte. Observera att den här medlemsposten måste ske först i JSON-objektet för att den här särskilda mappningen ska gälla. Detta representerar en avvikelse från vanlig JSON-bearbetning, där ordningen på medlemsposter inte är betydande.

Exempel:

Följande JSON-fragment mappar till XML.

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

XML är följande kod.

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

Observera att __type AII finns, men det finns ingen __type EII.

Men om ordningen i JSON är omvänd enligt följande exempel.

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

Motsvarande XML visas.

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

Det vill säga, __type upphör att ha särskild betydelse och mappar till en EII som vanligt, inte AII.

Undantags-/icke-kapslingsregler för AII:s [normaliserade värde] när de mappas till ett JSON-värde är desamma som för JSON-strängar som anges i raden "sträng" i den här tabellen.

Exempel:

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

till föregående exempel kan mappas till följande JSON.

{"__type":"\\abc"}

Vid en XML-till-JSON-mappning får den första EII:ns [lokala namn] inte vara "__type".

Tomt utrymme (ws) genereras aldrig i XML till JSON-mappning för objekt och ignoreras vid JSON-till XML-mappning.

Exempel: Följande JSON-fragment mappar till ett XML-element.

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

XML-elementet visas i följande kod.

<root type="object"> <ccc type="string">aaa</ccc> <ddd type="string">bbb</bar> </root >
matris 0 eller fler EIC:er En startmatris (vänster hakparentes) som i avsnitt 2.3 i JSON RFC, följt av en matrispost för varje EII enligt beskrivningen ytterligare. Om det finns fler än en EII finns det värdeavgränsare (kommatecken) mellan matrisposterna. Allt detta följs av en slutmatris.

Exempel: Följande XML-element mappar till ett JSON-fragment.

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

JSON-fragmentet är ["aaa","bbb"]

Tomt utrymme (ws) genereras aldrig i XML till JSON-mappning för matriser och ignoreras vid JSON-till XML-mappning.

Exempel: Ett JSON-fragment.

["aaa", "bbb"]

XML-elementet som det mappar till.

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

Medlemsposter fungerar på följande sätt:

  • Det inre elementets [lokala namn] mappar till den string del av member som definieras i avsnitt 2.2 i JSON RFC.

Exempel: Följande element mappar till ett JSON-fragment.

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

Följande JSON-fragment visas.

{"myLocalName":"aaa"}
  • I XML-till-JSON-mappningen är de tecken som måste vara undantagna i JSON undantagna och de andra är inte undantagna. Tecknet "/", även om det inte är ett tecken som måste vara undantaget, är ändå undantaget (det behöver inte vara undantaget för JSON till XML-mappning). Detta krävs för att stödja ASP.NET AJAX-format för DateTime data i JSON.

  • I JSON-till-XML-mappningen tas alla tecken (inklusive ej undantagna tecken, om det behövs) till att bilda en string som skapar ett [lokalt namn].

  • Inre element [underordnade] mappar till värdet i avsnitt 2.2, enligt JSON Type Attribute precis som för Root JSON Element. Flera nivåer av kapsling av EIIs (inklusive kapsling i matriser) tillåts.

Exempel: Följande element mappar till ett JSON-fragment.

<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 >

Följande JSON-fragment är vad det mappar till.

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

Kommentar

Det finns inget XML-kodningssteg i föregående mappning. Därför stöder WCF endast JSON-dokument där alla tecken i nyckelnamn är giltiga tecken i XML-elementnamn. JSON-dokumentet {"<":"a"} stöds till exempel inte eftersom < det inte är ett giltigt namn för ett XML-element.

Den omvända situationen (tecken som är giltiga i XML men inte i JSON) orsakar inga problem eftersom föregående mappning innehåller JSON-åtgärder för att undvika/ta bort inkapsling.

Matrisposter fungerar på följande sätt:

  • Det inre elementets [lokala namn] är "item".

  • Inre elementets [underordnade] mappning till värdet i avsnitt 2.3, enligt JSON-typattributet som det gör för rot-JSON-elementet. Flera nivåer av kapsling av EIIs (inklusive kapsling i objekt) tillåts.

Exempel: Följande element mappar till ett JSON-fragment.

<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>

Följande är JSON-fragmentet.

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

Se även