Mapowanie między formatami JSON i XML

Czytelnicy i autorzy wygenerowani przez JsonReaderWriterFactory interfejs API XML za pośrednictwem zawartości JavaScript Object Notation (JSON). Kod JSON koduje dane przy użyciu podzestawu literałów obiektów języka JavaScript. Czytelnicy i autorzy wyprodukowany przez tę fabrykę są również używane, gdy zawartość JSON jest wysyłana lub odbierana przez aplikacje Windows Communication Foundation (WCF) przy użyciu elementu WebMessageEncodingBindingElement lub WebHttpBinding.

Po zainicjowaniu zawartości JSON czytnik JSON zachowuje się w taki sam sposób, jak czytnik tekstu XML w przypadku wystąpienia kodu XML. Składnik zapisywania JSON, gdy dana sekwencja wywołań, które w czytniku tekstowym XML generuje określone wystąpienie XML, zapisuje zawartość JSON. Mapowanie między tym wystąpieniem kodu XML i zawartością JSON jest opisane w tym temacie do użycia w scenariuszach zaawansowanych.

Wewnętrznie kod JSON jest reprezentowany jako zestaw informacji XML podczas przetwarzania przez usługę WCF. Zwykle nie musisz zajmować się tą wewnętrzną reprezentacją, ponieważ mapowanie jest tylko jednym logicznym: kod JSON nie jest zwykle fizycznie konwertowany na kod XML w pamięci lub konwertowany na format JSON z formatu XML. Mapowanie oznacza, że interfejsy API XML są używane do uzyskiwania dostępu do zawartości JSON.

Gdy program WCF używa formatu JSON, zwykle jest to, że DataContractJsonSerializer element jest automatycznie podłączony przez WebScriptEnablingBehavior zachowanie lub zachowanie WebHttpBehavior , jeśli jest to konieczne. Funkcja DataContractJsonSerializer rozumie mapowanie między plikiem JSON a zestawem informacji XML i działa tak, jakby bezpośrednio zajmowała się formatem JSON. (Istnieje możliwość użycia elementu DataContractJsonSerializer z dowolnym czytnikiem lub zapisem XML ze zrozumieniem, że kod XML jest zgodny z poniższym mapowaniem).

W zaawansowanych scenariuszach może być konieczne bezpośrednie uzyskanie dostępu do następującego mapowania. Te scenariusze występują, gdy chcesz serializować i deserializować kod JSON w niestandardowy sposób, bez polegania na DataContractJsonSerializerobiekcie lub w przypadku bezpośredniego radzenia sobie z Message typem dla komunikatów zawierających kod JSON. Mapowanie JSON-XML jest również używane do rejestrowania komunikatów. W przypadku korzystania z funkcji rejestrowania komunikatów w programie WCF komunikaty JSON są rejestrowane jako xml zgodnie z mapowaniem opisanym w następnej sekcji.

Aby wyjaśnić koncepcję mapowania, poniższy przykład dotyczy dokumentu JSON.

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

Aby odczytać ten dokument JSON przy użyciu jednego z poprzednio wymienionych czytelników, użyj tej samej sekwencji wywołań XmlDictionaryReader , co w celu odczytania następującego dokumentu XML.

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

Ponadto jeśli komunikat JSON w przykładzie zostanie odebrany przez usługę WCF i zarejestrowany, w poprzednim dzienniku zostanie wyświetlony fragment XML.

Mapowanie między plikiem JSON i zestawem informacji XML

Formalnie mapowanie znajduje się między plikiem JSON zgodnie z opisem w specyfikacji RFC 4627 (z wyjątkiem niektórych ograniczeń złagodzonych i niektórych innych ograniczeń) oraz zestawu informacji XML (a nie tekstowego kodu XML) zgodnie z opisem w zestawie informacji XML. Zapoznaj się z tym tematem, aby zapoznać się z definicjami elementów informacji i pól w nawiasach kwadratowych [kwadratowych].

Pusty dokument JSON jest mapowy na pusty dokument XML, a pusty dokument XML jest mapowy na pusty dokument JSON. Na mapowaniu XML na JSON przed białym znakiem i końcowym białym znakiem po niedozwolonym dokumencie.

Mapowanie jest definiowane między elementem informacji o dokumencie (DII) lub elementem informacyjnym (EII) i formatem JSON. Właściwość EII lub diI [element dokumentu] jest określana jako główny element JSON. Pamiętaj, że fragmenty dokumentu (XML z wieloma elementami głównymi) nie są obsługiwane w tym mapowaniu.

Przykład: następujący dokument:

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

I następujący element:

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

Oba mają mapowanie na format JSON. Element <root> jest głównym elementem JSON w obu przypadkach.

Ponadto w przypadku dii należy wziąć pod uwagę następujące kwestie:

  • Niektóre elementy na liście [podrzędne] nie mogą być obecne. Nie należy polegać na tym fakcie podczas odczytywania kodu XML mapowanego z formatu JSON.

  • Lista [dzieci] nie zawiera żadnych elementów informacji o komentarzu.

  • Lista [podrzędne] nie zawiera żadnych elementów informacji DTD.

  • Lista [dzieci] nie zawiera żadnych elementów informacji osobowych ( <?xml…> deklaracja nie jest traktowana jako element informacyjny pi)

  • Zestaw [notations] jest pusty.

  • Zestaw [nieparzysowanych jednostek] jest pusty.

Przykład: poniższy dokument nie ma mapowania na kod JSON, ponieważ [elementy podrzędne] zawierają dane osobowe i komentarz.

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

Interfejs EII dla głównego elementu JSON ma następujące cechy:

  • [nazwa lokalna] ma wartość "root".

  • [nazwa przestrzeni nazw] nie ma wartości.

  • [prefiks] nie ma wartości.

  • [elementy podrzędne] mogą zawierać identyfikatory EI (które reprezentują elementy wewnętrzne zgodnie z opisem) lub ciI (elementy informacji o znakach zgodnie z opisem) lub żaden z nich, ale nie oba te elementy.

  • [atrybuty] może zawierać następujące opcjonalne elementy informacji o atrybutach (AII)

  • Atrybut typu JSON ("typ") zgodnie z opisem. Ten atrybut służy do zachowania typu JSON (ciąg, liczba, wartość logiczna, obiekt, tablica lub wartość null) w mapowanym kodzie XML.

  • Atrybut nazwy kontraktu danych ("__type") zgodnie z opisem. Ten atrybut może być obecny tylko wtedy, gdy atrybut typu JSON jest również obecny, a jego [znormalizowana wartość] jest "object". Ten atrybut jest używany przez DataContractJsonSerializer element , aby zachować informacje o typie kontraktu danych — na przykład w przypadkach polimorficznych, w których typ pochodny jest serializowany i gdzie oczekiwano typu podstawowego. Jeśli nie pracujesz z elementem DataContractJsonSerializer, w większości przypadków ten atrybut jest ignorowany.

  • [przestrzenie nazw w zakresie] zawierają powiązanie ciągu "xml" na http://www.w3.org/XML/1998/namespace zgodnie ze specyfikacją zestawu informacji.

  • [elementy podrzędne], [atrybuty] i [przestrzenie nazw w zakresie] nie mogą mieć żadnych elementów innych niż określone wcześniej i [atrybuty przestrzeni nazw] nie muszą mieć żadnych elementów członkowskich, ale nie polegają na tych faktach podczas odczytywania kodu XML mapowanego z formatu JSON.

Przykład: następujący dokument nie ma mapowania na format JSON, ponieważ [atrybuty przestrzeni nazw] nie są puste.

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

Sztuczna inteligencja atrybutu typu JSON ma następujące cechy:

  • [nazwa przestrzeni nazw] nie ma wartości.
  • [prefiks] nie ma wartości.
  • [nazwa lokalna] to "typ".
  • [znormalizowana wartość] jest jedną z możliwych wartości typu opisanych w poniższej sekcji.
  • [określony] to true.
  • [typ atrybutu] nie ma wartości.
  • [odwołania] nie ma wartości.

Atrybut AII dla nazwy kontraktu danych ma następujące cechy:

  • [nazwa przestrzeni nazw] nie ma wartości.
  • [prefiks] nie ma wartości.
  • [nazwa lokalna] to "__type" (dwa podkreślenia, a następnie "typ").
  • [znormalizowana wartość] jest dowolnym prawidłowym ciągiem Unicode — mapowanie tego ciągu na kod JSON zostało opisane w poniższej sekcji.
  • [określony] to true.
  • [typ atrybutu] nie ma wartości.
  • [odwołania] nie ma wartości.

Elementy wewnętrzne zawarte w głównym elemecie JSON lub innych elementach wewnętrznych mają następujące cechy:

  • [nazwa lokalna] może mieć dowolną wartość zgodnie z opisem.
  • [nazwa przestrzeni nazw], [prefiks], [elementy podrzędne], [atrybuty], [atrybuty przestrzeni nazw] i [przestrzenie nazw w zakresie] podlegają tym samym regułom co główny element JSON.

Zarówno w głównym elemenie JSON, jak i w elementach wewnętrznych atrybut typu JSON definiuje mapowanie na kod JSON i możliwe [dzieci] i ich interpretację. Atrybut [znormalizowana wartość] uwzględnia wielkość liter i musi być małymi literami i nie może zawierać białych znaków.

[znormalizowana wartość] atrybutu typu JSON AII Dozwolone [elementy podrzędne] odpowiedniego interfejsu EII Mapowanie na format JSON
string (lub brak typu AII typu JSON)

A string i brak typu JSON AI są takie same sprawia, że string wartość domyślna.

<root> string1</root> Dlatego mapuje na ciąg JSON string "string1".
Co najmniej 0 ciI Kod JSON (JSON string RFC, sekcja 2.5). Każdy char z nich jest znakiem odpowiadającym kodowi [znak] z interfejsu CII. Jeśli nie ma interfejsów CII, mapuje go na pusty kod JSON string.

Przykład: następujący element mapuje na fragment JSON:

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

Fragment JSON to "42".

Na mapowaniu XML na JSON znaki, które muszą zostać zmapowane jako znaki ucieczki, wszystkie inne mapują na znaki, które nie są ucieczki. Znak "/" jest specjalny — jest ucieczki, mimo że nie musi być (zapisany jako "\/").

Przykład: poniższy element mapuje na fragment JSON.

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

Fragment JSON to "the \"da\/ta\"".

Na mapowaniu JSON na XML wszelkie znaki ucieczki i znaki, które nie są poprawnie mapowane na odpowiedni [kod znaku].

Przykład: fragment JSON "\u0041BC" jest mapowy na następujący element XML.

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

Ciąg może być otoczony białym znakiem ('ws' w sekcji 2 dokumentu RFC JSON), który nie jest mapowany na kod XML.

Przykład: fragment JSON "ABC", (istnieją spacje przed pierwszym podwójnym cudzysłowem), mapuje na następujący element XML.

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

Wszelkie białe znaki w formacie XML są mapowania na białe znaki w formacie JSON.

Przykład: następujący element XML mapuje na fragment JSON.

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

Fragment JSON to "A BC".
number Co najmniej 1 interfejsy CII Kod JSON (JSON number RFC, sekcja 2.4), prawdopodobnie otoczony białym znakiem. Każdy znak w kombinacji liczby/białych znaków jest znakiem odpowiadającym kodowi [znak] z interfejsu CII.

Przykład: poniższy element mapuje na fragment JSON.

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

Fragment JSON to 42

(Białe znaki są zachowywane).
boolean 4 lub 5 ciI (które odpowiadają true lub false), ewentualnie otoczone dodatkowymi ciI odstępami białych znaków. Sekwencja ciągłej integracji odpowiadająca ciągowi "true" jest mapowana na literał true, a sekwencja ciągłej integracji odpowiadająca ciągowi "false" jest mapowana na literał false. Otaczające białe znaki są zachowywane.

Przykład: poniższy element mapuje na fragment JSON.

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

Fragment JSON to false.
null Brak dozwolonych. Literał null. W kodzie JSON do mapowania null XML element może być otoczony białym znakiem (ws' w sekcji 2), który nie jest mapowany na kod XML.

Przykład: poniższy element mapuje na fragment JSON.

<root type="null"/>

lub

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

:

Fragment JSON w obu przypadkach to Null.
object 0 lub więcej EII. A begin-object (lewy nawias klamrowy) jak w sekcji 2.2 RFC JSON, a następnie rekord elementu członkowskiego dla każdego interfejsu EII zgodnie z opisem. Jeśli istnieje więcej niż jeden interfejs EII, istnieją separatory wartości (przecinki) między rekordami składowymi. Po tym wszystkim następuje obiekt końcowy (prawy nawias klamrowy).

Przykład: następujący element mapuje na fragment JSON.

<root type="object">

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

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

</root >

Fragment JSON to {"type1":"aaa","type2":"bbb"}.

Jeśli atrybut Typu kontraktu danych znajduje się na mapowaniu XML na JSON, zostanie wstawiony dodatkowy rekord członkowski na początku. Jego nazwa to [nazwa lokalna] atrybutu typu kontraktu danych ("__type"), a jego wartością jest atrybut [znormalizowana wartość]. Z drugiej strony, w formacie JSON do mapowania XML, jeśli nazwa pierwszego rekordu członkowskiego to [nazwa lokalna] atrybutu Typu kontraktu danych (czyli "__type"), odpowiedni atrybut typu kontraktu danych znajduje się w mapowanym pliku XML, ale odpowiedni interfejs EII nie jest obecny. Należy pamiętać, że ten rekord członkowski musi występować najpierw w obiekcie JSON, aby to specjalne mapowanie było stosowane. Reprezentuje to odejście od zwykłego przetwarzania JSON, gdzie kolejność rekordów składowych nie jest znacząca.

Przykład:

Poniższy fragment JSON mapuje na kod XML.

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

Kod XML jest następujący.

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

Zwróć uwagę, że __type sztuczna inteligencja jest obecna, ale nie ma __type EII.

Jeśli jednak kolejność w formacie JSON zostanie odwrócona, jak pokazano w poniższym przykładzie.

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

Zostanie wyświetlony odpowiedni kod XML.

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

Oznacza to, że __type przestaje mieć specjalne znaczenie i mapuje je na sztuczną inteligencję jak zwykle, a nie sztuczną inteligencję.

Escaping/unescaping rules for the AII's [normalized value] when ma mapowane na wartość JSON są takie same jak w przypadku ciągów JSON określonych w wierszu "ciąg" tej tabeli.

Przykład:

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

do poprzedniego przykładu można zamapować na następujący kod JSON.

{"__type":"\\abc"}

Na mapowaniu XML na JSON pierwszy identyfikator EII [nazwa lokalna] nie może być "__type".

Białe znaki (ws) nigdy nie są generowane w formacie XML do mapowania JSON dla obiektów i są ignorowane w formacie JSON do mapowania XML.

Przykład: następujący fragment JSON mapuje na element XML.

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

Element XML jest wyświetlany w poniższym kodzie.

<root type="object"> <ccc type="string">aaa</ccc> <ddd type="string">bbb</bar> </root >
tablica 0 lub więcej interfejsów EI Tablica początek (lewy nawias kwadratowy) jak w sekcji 2.3 RFC JSON, a następnie rekord tablicy dla każdego interfejsu EII zgodnie z opisem. Jeśli istnieje więcej niż jeden interfejs EII, istnieją separatory wartości (przecinki) między rekordami tablicy. Wszystko to następuje po tablicy końcowej.

Przykład: następujący element XML mapuje na fragment JSON.

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

Fragment JSON jest ["aaa","bbb"]

Białe znaki (ws) nigdy nie są generowane w formacie XML do mapowania JSON dla tablic i są ignorowane w formacie JSON do mapowania XML.

Przykład: fragment JSON.

["aaa", "bbb"]

Element XML, do którego jest mapowy.

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

Rekordy członkowskie działają w następujący sposób:

  • Element wewnętrzny [nazwa lokalna] mapuje na string część member elementu zdefiniowaną w sekcji 2.2 specyfikacji RFC JSON.

Przykład: poniższy element mapuje na fragment JSON.

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

Zostanie wyświetlony następujący fragment JSON.

{"myLocalName":"aaa"}
  • Na mapowaniu XML na JSON znaki, które muszą być ucieczki w formacie JSON, są ucieczki, a pozostałe nie są ucieczki. Znak "/", mimo że nie jest znakiem, który musi zostać uniknięty, jest jednak ucieczki (nie musi być ucieczki w formacie JSON do mapowania XML). Jest to wymagane do obsługi formatu ASP.NET AJAX dla DateTime danych w formacie JSON.

  • Na mapowaniu JSON na XML wszystkie znaki (w tym znaki nieuniknięte, w razie potrzeby) są pobierane do utworzenia elementu string tworzącego [nazwę lokalną].

  • Elementy wewnętrzne [elementy podrzędne] są mapowane na wartość w sekcji 2.2, zgodnie z wartością podobną JSON Type Attribute do elementu Root JSON Element. Dozwolone są wiele poziomów zagnieżdżania interfejsów EI (w tym zagnieżdżania w tablicach).

Przykład: poniższy element 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 >

Poniższy fragment JSON jest mapowania na.

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

Uwaga

W poprzednim mapowaniu nie ma kroku kodowania XML. W związku z tym program WCF obsługuje tylko dokumenty JSON, w których wszystkie znaki w nazwach kluczy są prawidłowymi znakami w nazwach elementów XML. Na przykład dokument JSON {":"<a"} nie jest obsługiwany, ponieważ < nie jest prawidłową nazwą elementu XML.

Odwrotna sytuacja (znaki prawidłowe w formacie XML, ale nie w formacie JSON) nie powodują żadnych problemów, ponieważ poprzednie mapowanie zawiera kroki ucieczki/wyrejezowania kodu JSON.

Rekordy tablic działają w następujący sposób:

  • Element wewnętrzny [nazwa lokalna] jest "element".

  • Element wewnętrzny [elementy podrzędne] mapuje na wartość w sekcji 2.3, zgodnie z atrybutem typu JSON, tak jak w przypadku głównego elementu JSON. Dozwolone są wiele poziomów zagnieżdżania interfejsów EI (w tym zagnieżdżania w obiektach).

Przykład: poniższy element 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>

Poniżej znajduje się fragment JSON.

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

Zobacz też