Udostępnij za pośrednictwem


Autonomiczna serializacja JSON przy użyciu klasy DataContractJsonSerializer

Uwaga

Ten artykuł dotyczy DataContractJsonSerializerusługi . W przypadku większości scenariuszy obejmujących serializowanie i deserializacji danych JSON zalecamy interfejsy API w przestrzeni nazw System.Text.Json.

JSON (JavaScript Object Notation) to format danych zaprojektowany specjalnie do użycia przez kod JavaScript działający na stronach internetowych w przeglądarce. Jest to domyślny format danych używany przez usługi ASP.NET AJAX utworzone w programie Windows Communication Foundation (WCF).

Ten format można również użyć podczas tworzenia usług AJAX bez integracji z ASP.NET — w tym przypadku plik XML jest domyślny, ale można wybrać format JSON.

Jeśli na koniec potrzebujesz obsługi formatu JSON, ale nie tworzysz usługi AJAX, DataContractJsonSerializer umożliwia bezpośrednie serializowanie obiektów .NET w danych JSON i deserializacji takich danych z powrotem do wystąpień typów platformy .NET. Aby uzyskać opis sposobu, w jaki to zrobić, zobacz Instrukcje: serializowanie i deserializowanie danych JSON.

Podczas pracy z plikiem JSON obsługiwane są te same typy platformy .NET, z kilkoma wyjątkami, które są obsługiwane przez program DataContractSerializer. Aby uzyskać listę obsługiwanych typów, zobacz Typy obsługiwane przez serializator kontraktu danych. Obejmuje to większość typów pierwotnych, większość typów tablic i kolekcji, a także typy złożone używające elementów DataContractAttribute i DataMemberAttribute.

Mapuj typy platformy .NET na typy JSON

W poniższej tabeli przedstawiono korespondencję między typami .NET i typami JSON/JavaScript, gdy są mapowane przez procedury serializacji i deserializacji.

Typy platformy .NET JSON/JavaScript Uwagi
Wszystkie typy liczbowe, na przykład Int32, Decimal lub Double Liczba Wartości specjalne, takie jak Double.NaN, Double.PositiveInfinity i Double.NegativeInfinity nie są obsługiwane i powodują nieprawidłowy kod JSON.
Enum Liczba Zobacz "Wyliczenia i dane JSON" w dalszej części tego artykułu.
Boolean Wartość logiczna
String, Char String
TimeSpan, , GuidUri String Format tych typów w formacie JSON jest taki sam jak w formacie XML (zasadniczo przedział czasu w formacie trwania ISO 8601, identyfikator GUID w formacie "12345678-ABCD-ABCD-ABCD-1234567890AB" i identyfikator URI w postaci ciągu naturalnego, na przykład "http://www.example.com"). Aby uzyskać dokładne informacje, zobacz Data Contract Schema Reference (Dokumentacja schematu kontraktu danych).
XmlQualifiedName String Format to "name:namespace" (wszystko przed pierwszym dwukropkiem jest nazwą). Brak nazwy lub przestrzeni nazw. Jeśli nie ma przestrzeni nazw, można również pominąć dwukropek.
Array typu Byte Tablica liczb Każda liczba reprezentuje wartość jednego bajtu.
DateTime Data/godzina lub ciąg Zobacz daty/godziny i dane JSON w dalszej części tego artykułu.
DateTimeOffset Typ złożony Zobacz daty/godziny i dane JSON w dalszej części tego artykułu.
Typy XML i ADO.NET (XmlElement,

XElement. Tablice z wartościami XmlNode,

ISerializable,

DataSet).
String Zobacz sekcję Typy XML i kod JSON w tym artykule.
DBNull Pusty typ złożony --
Kolekcje, słowniki i tablice Tablica Zobacz sekcję Kolekcje, Słowniki i Tablice tego tematu.
Typy złożone (z zastosowanymi DataContractAttribute lub SerializableAttribute ) Typ złożony Składowe danych stają się członkami typu złożonego języka JavaScript.
Złożone typy implementowania interfejsu ISerializable ) Typ złożony Takie same jak inne złożone typy, ale niektóre ISerializable typy nie są obsługiwane — zobacz Obsługa ISerializable.
Null wartość dla dowolnego typu Null (zero) Typy wartości dopuszczalnych wartości są również obsługiwane i mapowane na format JSON w taki sam sposób, jak typy wartości niezwiązanych z wartościami null.

Wyliczenia i dane JSON

Wartości składowych wyliczenia są traktowane jako liczby w formacie JSON, co różni się od sposobu traktowania ich w kontraktach danych, gdzie są uwzględniane jako nazwy elementów członkowskich. Aby uzyskać więcej informacji na temat przetwarzania kontraktów danych, zobacz Typy wyliczenia w kontraktach danych.

  • Na przykład, jeśli masz public enum Color {red, green, blue, yellow, pink}, serializowanie yellow generuje liczbę 3, a nie ciąg "żółty".

  • Wszystkie enum elementy członkowskie można serializować. Atrybuty EnumMemberAttribute i NonSerializedAttribute są ignorowane, jeśli są używane.

  • Istnieje możliwość deserializacji nieistniejących enum wartości — na przykład wartość 87 można deserializować do poprzedniego wyliczenia Color, mimo że nie zdefiniowano odpowiedniej nazwy koloru.

  • Flagi enum nie są specjalne i są traktowane tak samo jak inne enum.

Daty/godziny i dane JSON

Format JSON nie obsługuje bezpośrednio dat i godzin. Są one jednak bardzo często używane i ASP.NET AJAX zapewnia specjalną obsługę tych typów. W przypadku korzystania z serwerów DateTime proxy ASP.NET AJAX typ w pełni odpowiada typowi DateTime w języku JavaScript.

  • Jeśli nie używasz DateTime ASP.NET, typ jest reprezentowany w formacie JSON jako ciąg ze specjalnym formatem opisanym w sekcji Informacje zaawansowane w tym temacie.

  • DateTimeOffset element jest reprezentowany w formacie JSON jako typ złożony: {"DateTime":d ateTime,"OffsetMinutes":offsetMinutes}. Element offsetMinutes członkowski jest przesunięciem czasu lokalnego z Greenwich Mean Time (GMT), nazywanym również uniwersalnym czasem koordynowanym (UTC) skojarzonym z lokalizacją interesującego zdarzenia. Element dateTime członkowski reprezentuje wystąpienie w czasie, gdy wystąpiło zdarzenie zainteresowania (ponownie staje się DateTime ono w języku JavaScript, gdy ASP.NET AJAX jest w użyciu i ciąg, gdy nie jest). W przypadku serializacji element dateTime członkowski jest zawsze serializowany w GMT. Tak więc, jeśli opis czasu 3:00 w Nowym Jorku, dateTime ma składnik czasu 8:00 i offsetMinutes wynosi 300 (minus 300 minut lub 5 godzin od GMT).

    Uwaga

    DateTime i DateTimeOffset obiekty, w przypadku serializacji do formatu JSON, zachowują tylko informacje o dokładności milisekundowej. Wartości pod milisekund (mikro/nanosekundy) są tracone podczas serializacji.

Typy XML i dane JSON

Typy XML stają się ciągami JSON.

  • Jeśli na przykład element członkowski danych "q" typu XElement zawiera <abc/>, kod JSON to {"q":"<abc/>"}.

  • Istnieją pewne specjalne reguły, które określają sposób opakowania kodu XML — aby uzyskać więcej informacji, zobacz sekcję Informacje zaawansowane w dalszej części tego artykułu.

  • Jeśli używasz ASP.NET AJAX i nie chcesz używać ciągów w języku JavaScript, ale zamiast tego chcesz, aby plik DOM XML był używany, ustaw ResponseFormat właściwość na XML na xml WebGetAttribute lub ResponseFormat właściwość na XML na WebInvokeAttribute.

Kolekcje, słowniki i tablice

Wszystkie kolekcje, słowniki i tablice są reprezentowane w formacie JSON jako tablice.

  • Każde dostosowanie, które używa elementu CollectionDataContractAttribute , jest ignorowane w reprezentacji JSON.

  • Słowniki nie są sposobem pracy bezpośrednio z plikiem JSON. Ciąg słownika,obiekt<> może nie być obsługiwany w taki sam sposób w programie WCF, jak oczekiwano podczas pracy z innymi technologiami JSON. Jeśli na przykład "abc" jest mapowany na "xyz", a wyrażenie "def" jest mapowane na 42 w słowniku, reprezentacja JSON nie jest {"abc":"xyz","def":42}, ale to [{"Key":"abc","Value":"xyz"},{"Key":"def","Value":42}].

  • Jeśli chcesz pracować bezpośrednio z plikiem JSON (dynamiczne uzyskiwanie dostępu do kluczy i wartości bez wstępnego definiowania sztywnego kontraktu), masz kilka opcji:

    • Rozważ użycie przykładu Serializacja JSON (AJAX) typu Weakly-typed( Weakly-typed JSON Serialization).

    • Rozważ użycie konstruktorów interfejsu ISerializable i deserializacji — te dwa mechanizmy umożliwiają dostęp do par klucz/wartość JSON odpowiednio na serializacji i deserializacji, ale nie działają w scenariuszach częściowego zaufania.

    • Rozważ pracę z mapowaniem między formatami JSON i XML zamiast przy użyciu serializatora.

    • Polimorfizm w kontekście serializacji odnosi się do możliwości serializacji typu pochodnego, w którym oczekiwano jego typu podstawowego. Istnieją specjalne reguły specyficzne dla formatu JSON podczas używania kolekcji polimorficznie, na przykład podczas przypisywania kolekcji do klasy Object. Ten problem jest bardziej szczegółowo omówiony w sekcji Informacje zaawansowane w dalszej części tego artykułu.

Dodatkowe szczegóły

Kolejność elementów członkowskich danych

Kolejność elementów członkowskich danych nie jest ważna w przypadku korzystania z formatu JSON. W szczególności, nawet jeśli Order jest ustawiona, dane JSON nadal mogą być deserializowane w dowolnej kolejności.

Typy JSON

Typ JSON nie musi być zgodny z poprzednią tabelą w przypadku deserializacji. Na przykład Int zwykle mapuje się na liczbę JSON, ale można ją również pomyślnie zdeserializować z ciągu JSON, o ile ten ciąg zawiera prawidłową liczbę. Oznacza to, że zarówno {"q":42} jak i {"q":"42"} są prawidłowe, jeśli istnieje Int element członkowski danych o nazwie "q".

Polimorfizm

Serializacja polimorficzna składa się z możliwości serializacji typu pochodnego, w którym oczekiwano jego typu podstawowego. Jest to obsługiwane w przypadku serializacji JSON przez program WCF porównywalny ze sposobem obsługi serializacji XML. Na przykład można serializować MyDerivedType , gdzie MyBaseType jest oczekiwana, lub serializować Int , gdzie Object jest oczekiwana.

Informacje o typie mogą zostać utracone podczas deserializacji typu pochodnego, jeśli typ podstawowy jest oczekiwany, chyba że deserializuje się typ złożony. Na przykład, jeśli Uri jest serializowany, gdzie Object jest oczekiwany, powoduje to ciąg JSON. Jeśli ten ciąg zostanie następnie zdeserializowany z powrotem do Objectelementu , zwracany jest program .NET String . Deserializator nie wie, że ciąg był początkowo typem Uri. Ogólnie rzecz biorąc, podczas oczekiwania Objectwszystkie ciągi JSON są deserializowane jako ciągi .NET, a wszystkie tablice JSON używane do serializacji kolekcji platformy .NET, słowników i tablic są deserializowane jako platforma .NET Array typu Object, niezależnie od rzeczywistego oryginalnego typu. Wartość logiczna JSON mapuje na platformę .NET Boolean. Jednak w przypadku Objectoczekiwania liczby JSON są deserializowane jako .NET Int32Decimal lub Double, gdzie najbardziej odpowiedni typ jest wybierany automatycznie.

Podczas deserializacji do typu interfejsu deserializuje się tak, DataContractJsonSerializer jakby zadeklarowany typ był obiektem.

Podczas pracy z własnymi typami bazowymi i pochodnymi zwykle KnownTypeAttributewymagany jest mechanizm , ServiceKnownTypeAttribute lub równoważny. Jeśli na przykład masz operację, która ma wartość zwracaną Animal i w rzeczywistości zwraca wystąpienie Cat (pochodzące z Animal), należy zastosować KnownTypeAttributeparametr , do Animal typu lub ServiceKnownTypeAttribute do operacji i określić Cat typ w tych atrybutach. Aby uzyskać więcej informacji, zobacz Znane typy kontraktów danych.

Aby uzyskać szczegółowe informacje na temat działania serializacji polimorficznej oraz omówienie niektórych ograniczeń, które należy przestrzegać podczas korzystania z niej, zobacz sekcję Informacje zaawansowane w dalszej części tego artykułu.

Wersje

Funkcje przechowywania wersji kontraktu IExtensibleDataObject danych, w tym interfejs, są w pełni obsługiwane w formacie JSON. Ponadto w większości przypadków można deserializować typ w jednym formacie (na przykład XML), a następnie serializować go w innym formacie (na przykład w formacie JSON) i zachować dane w IExtensibleDataObjectpliku . Aby uzyskać więcej informacji, zobacz Kontrakty danych zgodne z przekazywaniem. Pamiętaj, że kod JSON jest nieurządkowany, więc wszystkie informacje o zamówieniu zostaną utracone. Ponadto kod JSON nie obsługuje wielu par klucz/wartość o tej samej nazwie klucza. Na koniec wszystkie operacje na IExtensibleDataObject nich są z natury polimorficzne — jest to ich typ pochodny są przypisywane do Object, typu podstawowego dla wszystkich typów.

Kod JSON w adresach URL

W przypadku używania ASP.NET punktów końcowych AJAX z czasownikiem HTTP GET (przy użyciu atrybutu WebGetAttribute ) parametry przychodzące są wyświetlane w adresie URL żądania zamiast treści komunikatu. Kod JSON jest obsługiwany nawet w adresie URL żądania, więc jeśli masz operację, która przyjmuje Int nazwę "number" i Person typ złożony o nazwie "p", adres URL może przypominać następujący adres URL.

http://example.com/myservice.svc/MyOperation?number=7&p={"name":"John","age":42}

Jeśli używasz kontrolki menedżera skryptów AJAX ASP.NET i serwera proxy do wywoływania usługi, ten adres URL jest generowany automatycznie przez serwer proxy i nie jest widoczny. Nie można używać kodu JSON w adresach URL w punktach końcowych AJAX non-ASP.NET.

Zaawansowane informacje

Obsługa interfejsu ISerializable

Obsługiwane i nieobsługiwane typy ISerializable

Ogólnie rzecz biorąc, typy implementujące ISerializable interfejs są w pełni obsługiwane podczas serializacji/deserializacji JSON. Jednak niektóre z tych typów (w tym niektóre typy programu .NET Framework) są implementowane w taki sposób, że aspekty serializacji specyficzne dla formatu JSON powodują, że nie są one poprawnie deserializacji:

  • W programie ISerializabletyp poszczególnych składowych danych nigdy nie jest znany z wyprzedzeniem. Prowadzi to do sytuacji polimorficznej podobnej do deserializacji typów do obiektu. Jak wspomniano wcześniej, może to prowadzić do utraty informacji o typie w formacie JSON. Na przykład typ, który serializuje enum element w swojej ISerializable implementacji i próbuje wykonać deserializowanie bezpośrednio do elementu (bez odpowiednich rzutów), kończy się niepowodzeniem enum , ponieważ enum obiekt jest serializowany przy użyciu liczb JSON i JSON deserializowania w wbudowanych typach liczbowych platformy .NET (Int32, Decimal lub Double). Więc fakt, że liczba używana jako wartość jest enum utracona.

  • Typ ISerializable , który zależy od określonej kolejności deserializacji w konstruktorze deserializacji, może również nie wykonać deserializacji niektórych danych JSON, ponieważ większość serializatorów JSON nie gwarantuje żadnej określonej kolejności.

Typy fabryk

IObjectReference Chociaż interfejs jest ogólnie obsługiwany w formacie JSON, wszelkie typy wymagające funkcji "typu fabryki" (zwracanie wystąpienia innego typu niż GetRealObject(StreamingContext) typ implementujący interfejs) nie są obsługiwane.

Format przewodu daty/godziny

DateTime wartości są wyświetlane jako ciągi JSON w postaci "/Date(700000+0500)/", gdzie pierwsza liczba (700000 w podanym przykładzie) jest liczbą milisekund w strefie czasowej GMT, regularny (nieoświetlony) od północy, 1 stycznia 1970. Liczba może być ujemna, aby reprezentować wcześniejsze czasy. Część składająca się z "+0500" w przykładzie jest opcjonalna i wskazuje, że czas jest Local tego rodzaju — czyli należy przekonwertować na lokalną strefę czasową w deserializacji. Jeśli jest nieobecny, czas jest deserializowany jako Utc. Rzeczywista liczba ("0500" w tym przykładzie) i jej znak (+ lub -) są ignorowane.

Podczas serializacji DateTime, Local i Unspecified czasy są zapisywane z przesunięciem i Utc jest zapisywany bez.

Kod JavaScript klienta ASP.NET AJAX automatycznie konwertuje takie ciągi na wystąpienia języka JavaScript DateTime . Jeśli istnieją inne ciągi, które mają podobny formularz, który nie jest typu DateTime na platformie .NET, są również konwertowane.

Konwersja odbywa się tylko wtedy, gdy znaki "/" zostaną uniknięci (tj. kod JSON wygląda następująco: "\/Date(70000+0500)\/"), a z tego powodu koder JSON programu WCF (włączony przez WebHttpBinding) zawsze unika znaku "/".

Kod XML w ciągach JSON

XmlElement

XmlElement jest serializowany tak, jak jest, bez zawijania. Na przykład element członkowski danych "x" typu XmlElement zawierający <abc/> jest reprezentowany w następujący sposób:

{"x":"<abc/>"}

Tablice xmlnode

Array obiekty typu XmlNode są opakowane w element o nazwie ArrayOfXmlNode w standardowej przestrzeni nazw kontraktu danych dla typu. Jeśli "x" jest tablicą zawierającą węzeł atrybutu "N" w przestrzeni nazw "ns", która zawiera "value" i pusty węzeł elementu "M", reprezentacja jest następująca.

{"x":"<ArrayOfXmlNode xmlns=\"http://schemas.datacontract.org/2004/07/System.Xml\" a:N=\"value\" xmlns:a=\"ns\"><M/></ArrayOfXmlNode>"}

Atrybuty w pustej przestrzeni nazw na początku tablic XmlNode (przed innymi elementami) nie są obsługiwane.

Typy IXmlSerializable, w tym XElement i DataSet

ISerializable typy dzielą się na "typy zawartości", "Typy zestawów danych" i "typy elementów". Definicje tych typów można znaleźć w temacie XML i ADO.NET Types in Data Contracts (Typy XML i ADO.NET w kontraktach danych).

Typy "Content" i "DataSet" są serializowane podobnie jak Array obiekty XmlNode omówione w poprzedniej sekcji. Są one opakowane w element, którego nazwa i przestrzeń nazw odpowiadają nazwie kontraktu danych i przestrzeni nazw danego typu.

Typy "Element", takie jak są serializowane, podobnie XmlElement jak XElement wcześniej omówione w tym artykule.

Polimorfizm

Zachowywanie informacji o typie

Jak wspomniano wcześniej, polimorfizm jest obsługiwany w formacie JSON z pewnymi ograniczeniami. Język JavaScript jest słabo wpisanym językiem, a tożsamość typu zwykle nie jest problemem. Jednak w przypadku używania formatu JSON do komunikowania się między silnie typizowanego systemu (.NET) i słabo typizowanego systemu (JavaScript), warto zachować tożsamość typu. Na przykład typy o nazwach kontraktów danych "Square" i "Circle" pochodzą z typu o nazwie kontraktu danych "Kształt". Jeśli element "Circle" jest wysyłany z platformy .NET do języka JavaScript, a później jest zwracany do metody .NET, która oczekuje "Shape", warto wiedzieć, że dany obiekt był pierwotnie "Circle" — w przeciwnym razie wszelkie informacje specyficzne dla typu pochodnego (na przykład "radius" elementu członkowskiego danych w elemencie "Circle") mogą zostać utracone.

Aby zachować tożsamość typu, podczas serializacji typów złożonych w formacie JSON można dodać "wskazówkę typu", a deserializator rozpoznaje wskazówkę i działa odpowiednio. "Wskazówka typu" jest parą klucz/wartość JSON z nazwą klucza "__type" (dwa podkreślenia, a następnie słowo "type"). Wartość jest ciągiem JSON formularza "DataContractName:DataContractNamespace" (cokolwiek do pierwszego dwukropka jest nazwą). Korzystając z wcześniejszego przykładu, "Circle" można serializować w następujący sposób.

{"__type":"Circle:http://example.com/myNamespace","x":50,"y":70,"radius":10}

Wskazówka typu jest bardzo podobna do atrybutu xsi:type zdefiniowanego przez standard wystąpienia schematu XML i używanego podczas serializacji/deserializacji XML.

Członkowie danych o nazwie "__type" są zabronione z powodu potencjalnego konfliktu z wskazówką typu.

Zmniejszenie rozmiaru wskazówek typu

Aby zmniejszyć rozmiar komunikatów JSON, domyślny prefiks przestrzeni nazw kontraktu danych (http://schemas.datacontract.org/2004/07/) jest zastępowany znakiem "#". (Aby to zastąpienie było odwracalne, jest używana reguła ucieczki: jeśli przestrzeń nazw zaczyna się od znaków "#" lub "\", są one dołączane z dodatkowym znakiem "\"). W związku z tym, jeśli "Circle" jest typem w przestrzeni nazw .NET "MyApp.Shapes", domyślną przestrzenią nazw kontraktu danych jest http://schemas.datacontract.org/2004/07/MyApp. Kształty i reprezentacja JSON są następujące.

{"__type":"Circle:#MyApp.Shapes","x":50,"y":70,"radius":10}

Zarówno obcięte (#MyApp.Kształty), jak i pełne (http://schemas.datacontract.org/2004/07/MyApp.Shapes) nazwy są zrozumiałe w deserializacji.

Pozycja wskazówki typu w obiektach JSON

Należy pamiętać, że wskazówka typu musi pojawić się najpierw w reprezentacji JSON. Jest to jedyny przypadek, w którym kolejność par klucz/wartość jest ważna w przetwarzaniu JSON. Na przykład następujące informacje nie są prawidłowym sposobem określenia wskazówki dotyczącej typu.

{"x":50,"y":70,"radius":10,"__type":"Circle:#MyApp.Shapes"}

DataContractJsonSerializer Zarówno używane przez program WCF, jak i ASP.NET strony klienta AJAX zawsze emitują najpierw wskazówkę dotyczącą typu.

Wskazówki dotyczące typów mają zastosowanie tylko do typów złożonych

Nie ma możliwości emitowania wskazówki typu dla typów niezwiązanych. Jeśli na przykład operacja ma typ zwracany Object , ale zwraca okrąg, reprezentacja JSON może być jak pokazano wcześniej, a informacje o typie są zachowywane. Jeśli jednak zostanie zwrócony identyfikator URI, reprezentacja JSON jest ciągiem i faktem, że ciąg używany do reprezentowania identyfikatora URI zostanie utracony. Dotyczy to nie tylko typów pierwotnych, ale także kolekcji i tablic.

Kiedy są emitowane wskazówki dotyczące typu

Wskazówki dotyczące typów mogą znacznie zwiększyć rozmiar komunikatu (jednym ze sposobów ograniczenia tego problemu jest użycie krótszych przestrzeni nazw kontraktu danych, jeśli jest to możliwe). W związku z tym następujące reguły określają, czy są emitowane wskazówki dotyczące typu:

  • W przypadku używania ASP.NET AJAX wskazówki dotyczące typów są zawsze emitowane zawsze, jeśli jest to możliwe, nawet jeśli nie ma przypisania podstawowego/pochodnego — na przykład, nawet jeśli koło jest przypisane do okręgu. (Jest to wymagane, aby w pełni umożliwić proces wywoływania ze słabo typizowanego środowiska JSON do silnie typizowanego środowiska .NET bez zaskakującej utraty informacji).

  • W przypadku korzystania z usług AJAX bez integracji ASP.NET wskazówki dotyczące typów są emitowane tylko wtedy, gdy istnieje przypisanie podstawowe/pochodne — czyli emitowane, gdy koło jest przypisane do kształtu, ale Object nie w przypadku przypisania do okręgu. Zapewnia to minimalne informacje wymagane do poprawnego zaimplementowania klienta JavaScript, co zwiększa wydajność, ale nie chroni przed utratą informacji o typie niepoprawnie zaprojektowanych klientów. Unikaj przypisań bazowych/pochodnych w całości na serwerze, jeśli chcesz uniknąć radzenia sobie z tym problemem na kliencie.

  • W przypadku używania DataContractSerializer typu alwaysEmitTypeInformation parametr konstruktora umożliwia wybór między dwoma poprzednimi trybami, a wartość domyślna to "false" (tylko emituj wskazówki dotyczące typu, jeśli jest to wymagane).

Zduplikowane nazwy składowych danych

Informacje o typie pochodnym znajdują się w tym samym obiekcie JSON wraz z informacjami o typie podstawowym i mogą występować w dowolnej kolejności. Na przykład Shape może być reprezentowana w następujący sposób.

{"__type":"Shape:#MyApp.Shapes","x":50,"y":70}

Koło może być reprezentowane w następujący sposób.

{"__type":"Circle:#MyApp.Shapes","x":50, "radius":10,"y":70}

Jeśli typ podstawowy Shape zawiera również składową danych o nazwie "radius", prowadzi to do kolizji obu serializacji (ponieważ obiekty JSON nie mogą mieć powtarzających się nazw kluczy) i deserializacji (ponieważ nie jest jasne, czy "promień" odnosi się do Shape.radius lub Circle.radius). W związku z tym pojęcie "ukrywania właściwości" (składowe danych o tej samej nazwie na podstawie i klasach pochodnych) zwykle nie jest zalecane w klasach kontraktów danych, w rzeczywistości jest zabronione w przypadku formatu JSON.

Polimorfizm i typy IXmlSerializable

IXmlSerializable typy mogą być przypisywane polimorficznie do siebie tak jak zwykle, o ile są spełnione wymagania znane typy, zgodnie ze zwykłymi regułami kontraktu danych. Jednak serializowanie IXmlSerializable typu zamiast Object powoduje utratę informacji o typie w wyniku jest ciągiem JSON.

Polimorfizm i niektóre typy interfejsów

Zabronione jest serializowanie typu kolekcji lub typu, który implementuje IXmlSerializable , gdy typ inny niż kolekcja, który nie IXmlSerializable jest (z wyjątkiem Object) jest oczekiwany. Na przykład interfejs niestandardowy o nazwie IMyInterface i typ, który implementuje zarówno typ MyTypeint, jak IEnumerable<T> i IMyInterface. Nie można wrócić MyType z operacji, której zwracany typ to IMyInterface. Jest to spowodowane tym, że MyType musi być serializowana jako tablica JSON i wymaga wskazówki o typie, a jak określono wcześniej, nie można dołączyć wskazówki typu z tablicami, tylko w przypadku typów złożonych.

Znane typy i konfiguracja

Wszystkie znane mechanizmy typu używane przez DataContractSerializer element są również obsługiwane w ten sam sposób przez element DataContractJsonSerializer. Oba serializatory odczytują ten sam element konfiguracji, dataContractSerializer> w <pliku system.runtime.serialization>, aby odnaleźć znane typy dodane za pośrednictwem pliku konfiguracji.<

Kolekcje przypisane do obiektu

Kolekcje przypisane do obiektu są serializowane tak, jakby były kolekcjami implementowanymi IEnumerable<T>: tablicą JSON z każdym wpisem zawierającym wskazówkę typu, jeśli jest to typ złożony. Na przykład List<T> typ Shape przypisany do Object elementu wygląda następująco.

[{"__type":"Shape:#MyApp.Shapes","x":50,"y":70},
{"__type":"Shape:#MyApp.Shapes","x":58,"y":73},
{"__type":"Shape:#MyApp.Shapes","x":41,"y":32}]

W przypadku deserializacji z powrotem do Objectelementu :

  • Shape musi znajdować się na liście Znane typy. Posiadanie List<T> typu Shape w znanych typach nie ma wpływu. Należy pamiętać, że nie trzeba dodawać Shape do znanych typów serializacji w tym przypadku — odbywa się to automatycznie.

  • Kolekcja jest deserializacji jako Array typu Object zawierającego Shape wystąpienia.

Kolekcje pochodne przypisane do kolekcji bazowych

Gdy kolekcja pochodna jest przypisywana do kolekcji podstawowej, kolekcja jest zwykle serializowana tak, jakby była kolekcją typu podstawowego. Jeśli jednak nie można przypisać typu elementu kolekcji pochodnej do typu elementu kolekcji podstawowej, zgłaszany jest wyjątek.

Wskazówki i słowniki typów

Po przypisaniu słownika do Objectelementu każdy wpis Klucz i Wartość w słowniku jest traktowany tak, jakby został przypisany Object i otrzymuje wskazówkę typu.

Podczas serializacji typów słowników obiekt JSON zawierający elementy członkowskie "Klucz" i "Wartość" nie ma wpływu na alwaysEmitTypeInformation ustawienie i zawiera tylko wskazówkę typu, gdy powyższe reguły kolekcji wymagają.

Prawidłowe nazwy kluczy JSON

Serializator XML koduje nazwy kluczy, które nie są prawidłowymi nazwami XML. Na przykład element członkowski danych o nazwie "123" będzie miał zakodowaną nazwę, taką jak "_x0031__x0032__x0033_", ponieważ "123" jest nieprawidłową nazwą elementu XML (zaczyna się od cyfry). Podobna sytuacja może wystąpić w przypadku niektórych międzynarodowych zestawów znaków nieprawidłowych w nazwach XML. Aby uzyskać wyjaśnienie tego wpływu kodu XML na przetwarzanie JSON, zobacz Mapowanie między formatami JSON i XML.

Zobacz też