Zelfstandige JSON-serialisatie met Behulp van DataContractJsonSerializer
Notitie
Dit artikel gaat over DataContractJsonSerializer. Voor de meeste scenario's waarbij JSON wordt geserialiseerd en gedeserialiseerd, raden we de API's aan in de naamruimte System.Text.Json.
JSON (JavaScript Object Notation) is een gegevensindeling die speciaal is ontworpen voor gebruik door JavaScript-code die wordt uitgevoerd op webpagina's in de browser. Dit is de standaardgegevensindeling die wordt gebruikt door ASP.NET AJAX-services die zijn gemaakt in Windows Communication Foundation (WCF).
Deze indeling kan ook worden gebruikt bij het maken van AJAX-services zonder integratie met ASP.NET. In dit geval is XML de standaardinstelling, maar kan JSON worden gekozen.
Als u JSON-ondersteuning nodig hebt, maar geen AJAX-service maakt, DataContractJsonSerializer kunt u .NET-objecten rechtstreeks serialiseren in JSON-gegevens en dergelijke gegevens deserialiseren in exemplaren van .NET-typen. Zie How to: Serialize and Deserialize JSON Data (JSON-gegevens serialiseren en deserialiseren) voor een beschrijving van hoe u dit doet.
Wanneer u met JSON werkt, worden dezelfde .NET-typen ondersteund, met enkele uitzonderingen, zoals wordt ondersteund door de DataContractSerializer. Zie Typen die worden ondersteund door de Serializer van het gegevenscontract voor een lijst met ondersteunde typen. Dit omvat de meeste primitieve typen, de meeste matrix- en verzamelingstypen, evenals complexe typen die gebruikmaken van en DataContractAttributeDataMemberAttribute.
.NET-typen toewijzen aan JSON-typen
In de volgende tabel ziet u de correspondentie tussen .NET-typen en JSON-/JavaScript-typen wanneer deze zijn toegewezen door serialisatie- en deserialisatieprocedures.
.NET-typen | JSON/JavaScript | Opmerkingen |
---|---|---|
Alle numerieke typen, bijvoorbeeld Int32of DecimalDouble | Aantal | Speciale waarden zoals Double.NaN en Double.PositiveInfinity Double.NegativeInfinity worden niet ondersteund en resulteren in ongeldige JSON. |
Enum | Aantal | Zie 'Opsommingen en JSON' verderop in dit artikel. |
Boolean | Booleaanse waarde | |
String, Char | String | |
TimeSpan, , GuidUri | String | De indeling van deze typen in JSON is hetzelfde als in XML (in wezen de tijdsduur in de indeling ISO 8601 Duur, GUID in de indeling 12345678-ABCD-ABCD-ABCD-1234567890AB, en URI in de natuurlijke tekenreeksvorm zoals "http://www.example.com" ). Zie Data Contract Schema Reference (Schemareferentie voor gegevenscontract) voor nauwkeurige informatie. |
XmlQualifiedName | String | De indeling is 'name:namespace' (alles voordat de eerste dubbele punt de naam is). De naam of de naamruimte kan ontbreken. Als er geen naamruimte is, kan de dubbele punt ook worden weggelaten. |
Array van het type Byte | Matrix met getallen | Elk getal vertegenwoordigt de waarde van één byte. |
DateTime | Datum/tijd of tekenreeks | Zie Datums/tijden en JSON verderop in dit artikel. |
DateTimeOffset | Complex type | Zie Datums/tijden en JSON verderop in dit artikel. |
XML- en ADO.NET-typen (XmlElement, XElement. Matrices van XmlNode, ISerializable, DataSet). |
String | Zie de sectie XML-typen en JSON van dit artikel. |
DBNull | Leeg complex type | -- |
Verzamelingen, woordenlijsten en matrices | Matrix | Zie de sectie Verzamelingen, woordenlijsten en matrices van dit onderwerp. |
Complexe typen (met de DataContractAttribute of SerializableAttribute toegepaste) | Complex type | Gegevensleden worden lid van het complexe JavaScript-type. |
Complexe typen die de ISerializable interface implementeren) | Complex type | Hetzelfde als andere complexe typen, maar sommige ISerializable typen worden niet ondersteund. Zie ISerializable Support. |
Null waarde voor elk type |
Null | Typen null-waarden worden ook ondersteund en toegewezen aan JSON op dezelfde manier als niet-null-waardetypen. |
Opsommingen en JSON
De waarden van opsommingsleden worden behandeld als getallen in JSON. Dit verschilt van de manier waarop ze worden behandeld in gegevenscontracten, waarbij ze als lidnamen worden opgenomen. Zie Opsommingstypen in Gegevenscontracten voor meer informatie over de gegevenscontractbehandeling.
Als u
public enum Color {red, green, blue, yellow, pink}
bijvoorbeeld hebt, produceert serialiserenyellow
het getal 3 en niet de tekenreeks 'geel'.Alle
enum
leden zijn serialiseerbaar. De EnumMemberAttribute en de NonSerializedAttribute kenmerken worden genegeerd als ze worden gebruikt.Het is mogelijk om een niet-bestaande
enum
waarde te deserialiseren, bijvoorbeeld de waarde 87 kan worden gedeserialiseerd in de vorige color-enum, zelfs als er geen overeenkomende kleurnaam is gedefinieerd.Een vlag
enum
is niet speciaal en wordt hetzelfde behandeld als andereenum
.
Datums/tijden en JSON
De JSON-indeling biedt geen rechtstreekse ondersteuning voor datums en tijden. Ze worden echter zeer vaak gebruikt en ASP.NET AJAX biedt speciale ondersteuning voor deze typen. Wanneer u ASP.NET AJAX-proxy's gebruikt, komt het DateTime type in .NET volledig overeen met het DateTime
type in JavaScript.
Wanneer u geen ASP.NET gebruikt, wordt een DateTime type in JSON weergegeven als een tekenreeks met een speciale indeling die wordt beschreven in de sectie Geavanceerde informatie van dit onderwerp.
DateTimeOffset wordt in JSON weergegeven als een complex type: {"DateTime":d ateTime,"OffsetMinutes":offsetMinutes}. Het
offsetMinutes
lid is de lokale tijd offset van Greenwich Mean Time (GMT), ook wel Coordinated Universal Time (UTC) genoemd, gekoppeld aan de locatie van het evenement van belang. HetdateTime
lid vertegenwoordigt het exemplaar op het moment waarop de gebeurtenis van belang is opgetreden (opnieuw wordt het eenDateTime
in JavaScript wanneer ASP.NET AJAX wordt gebruikt en een tekenreeks wanneer dit niet het geval is). Bij serialisatie wordt hetdateTime
lid altijd geserialiseerd in GMT. Dus, als een beschrijving van 3:00 uur New York tijd,dateTime
heeft een tijdcomponent van 8:00 uur enoffsetMinutes
zijn 300 (min 300 minuten of 5 uur van GMT).Notitie
DateTime en DateTimeOffset objecten behouden, wanneer ze naar JSON zijn geserialiseerd, alleen informatie tot precisie in milliseconden. Waarden van minder dan milliseconden (micro/nanoseconden) gaan verloren tijdens de serialisatie.
XML-typen en JSON
XML-typen worden JSON-tekenreeksen.
Als een gegevenslid van het type XElement bijvoorbeeld abc/>bevat<, is de JSON {"q":"<abc/>"}.
Er zijn enkele speciale regels die aangeven hoe XML wordt verpakt. Zie de sectie Geavanceerde informatie verderop in dit artikel voor meer informatie.
Als u ASP.NET AJAX gebruikt en geen tekenreeksen in JavaScript wilt gebruiken, maar in plaats daarvan de XML-DOM wilt gebruiken, stelt u de ResponseFormat eigenschap in op XML op WebGetAttribute XML of de ResponseFormat eigenschap op XML op de WebInvokeAttribute.
Verzamelingen, woordenlijsten en matrices
Alle verzamelingen, woordenlijsten en matrices worden in JSON weergegeven als matrices.
Aanpassingen die gebruikmaken van de toepassing CollectionDataContractAttribute , worden genegeerd in de JSON-weergave.
Woordenlijsten zijn geen manier om rechtstreeks met JSON te werken. Woordenlijsttekenreeks<, object> wordt mogelijk niet op dezelfde manier ondersteund in WCF als verwacht van het werken met andere JSON-technologieën. Als 'abc' bijvoorbeeld is toegewezen aan 'xyz' en 'def' is toegewezen aan 42 in een woordenlijst, is de JSON-weergave niet {"abc":"xyz","def":42} maar is [{"Key":"abc","Value":"xyz"},{"Key":"def","Value":42}] in plaats daarvan.
Als u rechtstreeks met JSON wilt werken (toegang tot sleutels en waarden dynamisch wilt gebruiken zonder vooraf een star contract te definiëren), hebt u verschillende opties:
Overweeg het gebruik van het ajax-voorbeeld (Weakly-typed JSON Serialization).
Overweeg het gebruik van de ISerializable interface- en deserialisatieconstructors. Met deze twee mechanismen hebt u respectievelijk toegang tot JSON-sleutel-/waardeparen voor serialisatie en deserialisatie, maar werkt u niet in gedeeltelijke vertrouwensscenario's.
Overweeg om te werken met de toewijzing tussen JSON en XML in plaats van een serializer te gebruiken.
Polymorfisme in de context van serialisatie verwijst naar de mogelijkheid om een afgeleid type te serialiseren waar het basistype wordt verwacht. Er zijn speciale JSON-specifieke regels wanneer u verzamelingen polymorf gebruikt, wanneer u bijvoorbeeld een verzameling toewijst aan een Object. Dit probleem wordt verderop in dit artikel uitgebreider besproken in de sectie Geavanceerde informatie.
Aanvullende details
Volgorde van gegevensleden
Volgorde van gegevensleden is niet belangrijk bij het gebruik van JSON. Zelfs als Order deze is ingesteld, kunnen JSON-gegevens nog steeds in elke volgorde worden gedeserialiseerd.
JSON-typen
Het JSON-type hoeft niet overeen te komen met de voorgaande tabel voor deserialisatie. Een normaal gesproken Int
toewijzing aan een JSON-getal, maar het kan ook worden gedeserialiseerd vanuit een JSON-tekenreeks zolang die tekenreeks een geldig getal bevat. Dat wil gezegd: {"q":42} en {"q":"42"} zijn geldig als er een Int
gegevenslid met de naam q is.
Polymorfisme
Polymorfische serialisatie bestaat uit de mogelijkheid om een afgeleid type te serialiseren waar het basistype wordt verwacht. Dit wordt ondersteund voor JSON-serialisatie door WCF, vergelijkbaar met de manier waarop XML-serialisatie wordt ondersteund. U kunt bijvoorbeeld serialiseren MyDerivedType
waar MyBaseType
wordt verwacht of waar wordt geserialiseerd Int
waar Object
wordt verwacht.
Typegegevens gaan mogelijk verloren wanneer een afgeleid type wordt gedeserialiseerd als het basistype wordt verwacht, tenzij u een complex type deserialiseert. Als er bijvoorbeeld Uri een geserialiseerde locatie Object wordt verwacht, resulteert dit in een JSON-tekenreeks. Als deze tekenreeks vervolgens wordt gedeserialiseerd naar Object, wordt een .NET String geretourneerd. De deserializer weet niet dat de tekenreeks aanvankelijk van het type Uriwas. Wanneer u verwacht Object, worden alle JSON-tekenreeksen gedeserialiseerd als .NET-tekenreeksen en worden alle JSON-matrices die worden gebruikt voor het serialiseren van .NET-verzamelingen, woordenlijsten en matrices gedeserialiseerd als .NET Array van het type Object, ongeacht wat het oorspronkelijke type was geweest. Een JSON-booleaanse waarde wordt toegewezen aan een .NET Boolean. Wanneer u echter een ObjectJSON-nummer verwacht, worden gedeserialiseerd als .NET Int32Decimal ofDouble, waarbij het meest geschikte type automatisch wordt gekozen.
Bij het deserialiseren in een interfacetype, wordt het DataContractJsonSerializer ontserialiseerd alsof het gedeclareerde type object was.
Wanneer u met uw eigen basis en afgeleide typen werkt, is KnownTypeAttributeServiceKnownTypeAttribute normaal gesproken een equivalent mechanisme vereist. Als u bijvoorbeeld een bewerking hebt die een Animal
retourwaarde heeft en daadwerkelijk een exemplaar van Cat
(afgeleid van Animal
) retourneert, moet u het KnownTypeAttribute, op het Animal
type of de ServiceKnownTypeAttribute bewerking toepassen en het Cat
type in deze kenmerken opgeven. Zie Bekende typen gegevenscontracten voor meer informatie.
Zie de sectie Geavanceerde informatie verderop in dit artikel voor meer informatie over hoe polymorfe serialisatie werkt en een bespreking van enkele van de beperkingen die moeten worden gerespecteerd wanneer u deze gebruikt.
Versiebeheer
De functies voor versiebeheer van gegevenscontracten, inclusief de IExtensibleDataObject interface, worden volledig ondersteund in JSON. Bovendien is het in de meeste gevallen mogelijk om een type in één indeling (bijvoorbeeld XML) te deserialiseren en deze vervolgens te serialiseren in een andere indeling (bijvoorbeeld JSON) en de gegevens nog steeds in IExtensibleDataObjectte bewaren. Zie Forward-Compatible Data Contracts voor meer informatie. Houd er rekening mee dat JSON niet is gerangschikt, zodat alle ordergegevens verloren gaan. Bovendien biedt JSON geen ondersteuning voor meerdere sleutel-/waardeparen met dezelfde sleutelnaam. Ten slotte zijn alle bewerkingen IExtensibleDataObject inherent polymorf- dat is hun afgeleide type worden toegewezen Objectaan , het basistype voor alle typen.
JSON in URL's
Wanneer u ASP.NET AJAX-eindpunten gebruikt met het HTTP GET-werkwoord (met behulp van het WebGetAttribute kenmerk), worden binnenkomende parameters weergegeven in de aanvraag-URL in plaats van de berichttekst. JSON wordt zelfs ondersteund in de aanvraag-URL, dus als u een bewerking hebt die een Int
zogenaamde 'getal' en een Person
complex type met de naam 'p' gebruikt, lijkt de URL mogelijk op de volgende URL.
http://example.com/myservice.svc/MyOperation?number=7&p={"name":"John","age":42}
Als u een ASP.NET AJAX Script Manager-besturingselement en proxy gebruikt om de service aan te roepen, wordt deze URL automatisch gegenereerd door de proxy en wordt deze niet gezien. JSON kan niet worden gebruikt in URL's op non-ASP.NET AJAX-eindpunten.
Geavanceerde informatie
Ondersteuning voor ISerializable
Ondersteunde en niet-ondersteunde typen ISerializable
Over het algemeen worden typen die de ISerializable interface implementeren volledig ondersteund bij het serialiseren/deserialiseren van JSON. Sommige van deze typen (waaronder sommige .NET Framework-typen) worden echter zodanig geïmplementeerd dat de JSON-specifieke serialisatieaspecten ervoor zorgen dat ze niet correct deserialiseren:
Hiermee ISerializablewordt het type afzonderlijke gegevensleden nooit van tevoren bekend. Dit leidt tot een polymorfe situatie die vergelijkbaar is met het deserialiseren van typen in een object. Zoals eerder vermeld, kan dit leiden tot verlies van typegegevens in JSON. Een type dat bijvoorbeeld een
enum
in de ISerializable implementatie serialiseert en probeert deserialiseren rechtstreeks in eenenum
(zonder juiste casts) te deserialiseren, omdat eenenum
getal wordt geserialiseerd met behulp van getallen in JSON- en JSON-getallen deserialiseren in ingebouwde .NET-numerieke typen (Int32, Decimaal of Dubbel). Het feit dat het getal dat vroeger eenenum
waarde was, gaat dus verloren.Een ISerializable type dat afhankelijk is van een bepaalde volgorde van deserialisatie in de deserialisatieconstructor, kan ook bepaalde JSON-gegevens deserialiseren, omdat de meeste JSON-serializers geen specifieke volgorde garanderen.
Fabriekstypen
Hoewel de IObjectReference interface in het algemeen wordt ondersteund in JSON, worden alle typen waarvoor de functie Factory-type is vereist (waarbij een exemplaar van een ander type wordt geretourneerd dan het type GetRealObject(StreamingContext) dat de interface implementeert) niet ondersteund.
Datum/tijd-draadnotatie
DateTime waarden worden weergegeven als JSON-tekenreeksen in de vorm van '/Date(700000+0500)/', waarbij het eerste getal (7000000 in het voorbeeld) het aantal milliseconden in de GMT-tijdzone is, normale (niet-zomertijd) tijd sinds middernacht, 1 januari 1970. Het getal kan negatief zijn om eerdere tijden weer te geven. Het deel dat uit '+0500' in het voorbeeld bestaat, is optioneel en geeft aan dat de tijd van het Local type is, dat wil gezegd, moet worden geconverteerd naar de lokale tijdzone voor deserialisatie. Als het afwezig is, wordt de tijd gedeserialiseerd als Utc. Het werkelijke getal ('0500' in dit voorbeeld) en het bijbehorende teken (+ of -) worden genegeerd.
Wanneer u serialiseert DateTimeen UnspecifiedLocal tijden worden geschreven met een offset en Utc zonder geschreven.
De javaScript-code van de ASP.NET AJAX-client converteert dergelijke tekenreeksen automatisch naar JavaScript-exemplaren DateTime
. Als er andere tekenreeksen zijn die een vergelijkbare vorm hebben die niet van het type DateTime in .NET zijn, worden ze ook geconverteerd.
De conversie vindt alleen plaats als de '/'-tekens zijn ontsnapt (dat wil gezegd: de JSON ziet eruit als \/Date(700000+0500)\/), en om deze reden ontsnapt de JSON-encoder van WCF (ingeschakeld door de WebHttpBinding) altijd aan het teken '/'.
XML in JSON-tekenreeksen
XmlElement
XmlElement wordt geserialiseerd zoals dat is, zonder wrapping. Gegevenslid 'x' van het type XmlElement dat abc/> bevat<, wordt bijvoorbeeld als volgt weergegeven:
{"x":"<abc/>"}
Matrices van XmlNode
Array objecten van het type XmlNode worden verpakt in een element met de naam ArrayOfXmlNode in de standaardnaamruimte voor het gegevenscontract voor het type. Als 'x' een matrix is die kenmerkknooppunt 'N' bevat in naamruimte 'ns' die 'waarde' en een leeg elementknooppunt 'M' bevat, is de weergave als volgt.
{"x":"<ArrayOfXmlNode xmlns=\"http://schemas.datacontract.org/2004/07/System.Xml\" a:N=\"value\" xmlns:a=\"ns\"><M/></ArrayOfXmlNode>"}
Kenmerken in de lege naamruimte aan het begin van XmlNode-matrices (vóór andere elementen) worden niet ondersteund.
IXmlSerializable Types, waaronder XElement en DataSet
ISerializable typen worden onderverdeeld in 'inhoudstypen', 'Gegevenssettypen' en 'elementtypen'. Zie XML- en ADO.NET-typen in gegevenscontracten voor definities van deze typen.
De typen 'Inhoud' en 'DataSet' worden geserialiseerd zoals Array objecten die XmlNode in de vorige sectie zijn besproken. Ze worden verpakt in een element waarvan de naam en naamruimte overeenkomt met de naam van het gegevenscontract en de naamruimte van het type in kwestie.
'Element'-typen, zoals worden geserialiseerd als XElement zodanig, vergelijkbaar met XmlElement eerder besproken in dit artikel.
Polymorfisme
Typegegevens behouden
Zoals eerder vermeld, wordt polymorfisme ondersteund in JSON met enkele beperkingen. JavaScript is een zwak getypte taal en typeidentiteit is normaal gesproken geen probleem. Wanneer u echter JSON gebruikt om te communiceren tussen een sterk getypt systeem (.NET) en een zwak getypt systeem (JavaScript), is het handig om de typeidentiteit te behouden. Typen met gegevenscontractnamen 'Vierkant' en 'Cirkel' zijn bijvoorbeeld afgeleid van een type met de naam van het gegevenscontract 'Shape'. Als 'Circle' wordt verzonden van .NET naar JavaScript en later wordt geretourneerd naar een .NET-methode die verwacht dat 'Shape' wordt verwacht, is het handig voor de .NET-zijde om te weten dat het betreffende object oorspronkelijk een 'Cirkel' was. Anders kan informatie die specifiek is voor het afgeleide type (bijvoorbeeld 'radius'-gegevenslid op 'Cirkel') verloren gaan.
Als u de typeidentiteit wilt behouden, kan bij het serialiseren van complexe typen naar JSON een 'typehint' worden toegevoegd en herkent de deserializer de hint en handelt deze op de juiste manier. De 'typehint' is een JSON-sleutel/waardepaar met de sleutelnaam '__type' (twee onderstrepingstekens gevolgd door het woord 'type'). De waarde is een JSON-tekenreeks van het formulier 'DataContractName:DataContractNamespace' (alles tot aan de eerste dubbele punt is de naam). In het eerdere voorbeeld kan Cirkel als volgt worden geserialiseerd.
{"__type":"Circle:http://example.com/myNamespace","x":50,"y":70,"radius":10}
De typehint is vergelijkbaar met het xsi:type
kenmerk dat is gedefinieerd door de standaard xml-schema-instantie en wordt gebruikt bij het serialiseren/deserialiseren van XML.
Gegevensleden met de naam '__type' zijn verboden vanwege een mogelijk conflict met de typehint.
De grootte van hints voor typen verkleinen
Als u de grootte van JSON-berichten wilt verkleinen, wordt het standaardvoorvoegsel voor de naamruimte van het gegevenscontract (http://schemas.datacontract.org/2004/07/
) vervangen door het teken #. (Als u deze vervanging omkeerbaar wilt maken, wordt een escape-regel gebruikt: als de naamruimte begint met de tekens '#' of '\', worden deze toegevoegd met een extra '\'-teken). Als 'Circle' dus een type is in de .NET-naamruimte 'MyApp.Shapes', is http://schemas.datacontract.org/2004/07/MyApp
de standaardnaamruimte van het gegevenscontract. Shapes en de JSON-weergave zijn als volgt.
{"__type":"Circle:#MyApp.Shapes","x":50,"y":70,"radius":10}
Zowel de afgekapte (#MyApp.Shapes) als de volledige (http://schemas.datacontract.org/2004/07/MyApp.Shapes
) namen worden begrepen bij deserialisatie.
Positie van hint typen in JSON-objecten
Houd er rekening mee dat de typehint eerst moet worden weergegeven in de JSON-weergave. Dit is het enige geval waarin volgorde van sleutel-/waardeparen belangrijk is in JSON-verwerking. Het volgende is bijvoorbeeld geen geldige manier om de typehint op te geven.
{"x":50,"y":70,"radius":10,"__type":"Circle:#MyApp.Shapes"}
Zowel de DataContractJsonSerializer clientpagina's van WCF als ASP.NET AJAX verzenden altijd eerst de typehint.
Typehints zijn alleen van toepassing op complexe typen
Er is geen manier om een typehint te verzenden voor niet-complexe typen. Als een bewerking bijvoorbeeld een Object retourtype heeft, maar een cirkel retourneert, kan de JSON-weergave worden weergegeven zoals eerder wordt weergegeven en blijft de typegegevens behouden. Als URI echter wordt geretourneerd, is de JSON-weergave een tekenreeks en gaat de tekenreeks die wordt gebruikt om een URI weer te geven verloren. Dit geldt niet alleen voor primitieve typen, maar ook voor verzamelingen en matrices.
Wanneer worden hints voor typen verzonden
Typehints kunnen de berichtgrootte aanzienlijk vergroten (een manier om dit te verhelpen is het gebruik van kortere naamruimten voor gegevenscontract indien mogelijk). Daarom bepalen de volgende regels of type hints worden verzonden:
Wanneer u ASP.NET AJAX gebruikt, worden hints altijd indien mogelijk verzonden, zelfs als er geen basis-/afgeleide toewijzing is, bijvoorbeeld als een cirkel is toegewezen aan een cirkel. (Dit is vereist om het proces van aanroepen vanuit de zwak getypte JSON-omgeving volledig in te schakelen in de sterk getypeerde .NET-omgeving zonder verrassend verlies van informatie.)
Bij het gebruik van AJAX-services zonder ASP.NET-integratie worden hints voor typen alleen verzonden wanneer er een basis-/afgeleide toewijzing is, dat wil gezegd, verzonden wanneer Cirkel wordt toegewezen aan Shape of Object niet wanneer deze is toegewezen aan Cirkel. Dit biedt de minimale informatie die nodig is om een JavaScript-client correct te implementeren, waardoor de prestaties worden verbeterd, maar niet wordt beschermd tegen typegegevensverlies bij onjuist ontworpen clients. Vermijd basis-/afgeleide toewijzingen helemaal op de server als u wilt voorkomen dat dit probleem op de client wordt opgelost.
Wanneer u het DataContractSerializer type gebruikt, kunt u met de
alwaysEmitTypeInformation
constructorparameter kiezen tussen de voorgaande twee modi, waarbij de standaardwaarde 'false
' is (indien nodig alleen hints voor het type verzenden).
Namen van gegevenslid dupliceren
Afgeleide typegegevens zijn aanwezig in hetzelfde JSON-object samen met basistypegegevens en kunnen in elke volgorde voorkomen. Kan bijvoorbeeld Shape
als volgt worden weergegeven.
{"__type":"Shape:#MyApp.Shapes","x":50,"y":70}
Overwegende dat Circle als volgt kan worden weergegeven.
{"__type":"Circle:#MyApp.Shapes","x":50, "radius":10,"y":70}
Als het basistype Shape
ook een gegevenslid met de naam 'radius
' bevat, leidt dit tot een botsing op beide serialisaties (omdat JSON-objecten geen herhalende sleutelnamen kunnen hebben) en deserialisatie (omdat het onduidelijk is of 'radius' verwijst naar Shape.radius
of Circle.radius
). Daarom wordt het concept 'eigenschap verbergen' (gegevensleden van dezelfde naam op basis en afgeleide klassen) over het algemeen niet aanbevolen in gegevenscontractklassen, maar is het in feite verboden in het geval van JSON.
Polymorfisme en IXmlSerializable Types
IXmlSerializable typen kunnen polymorf aan elkaar worden toegewezen, zoals gebruikelijk, zolang aan de vereisten voor bekende typen wordt voldaan, volgens de gebruikelijke regels voor gegevenscontracten. Het serialiseren van een IXmlSerializable type in plaats van Object resultaten resulteert echter in verlies van typegegevens omdat het resultaat een JSON-tekenreeks is.
Polymorfisme en bepaalde interfacetypen
Het is verboden om een verzamelingstype of een type te serialiseren dat wordt geïmplementeerd IXmlSerializable wanneer een niet-verzamelingstype niet IXmlSerializable (met uitzondering van Object) wordt verwacht. Een aangepaste interface die bijvoorbeeld wordt aangeroepen IMyInterface
en een type waarmee zowel IEnumerable<T> het type als het type MyType
int
IMyInterface
wordt geïmplementeerd. Het is verboden om terug te keren MyType
van een bewerking waarvan het retourtype is IMyInterface
. Dit komt doordat MyType
moet worden geserialiseerd als een JSON-matrix en een typehint vereist, en zoals eerder is aangegeven, kunt u geen typehint met matrices opnemen, alleen met complexe typen.
Bekende typen en configuratie
Alle bekende typemechanismen die door het DataContractSerializer type worden gebruikt, worden ook op dezelfde manier ondersteund door de DataContractJsonSerializer. Beide serializers lezen hetzelfde configuratie-element, <dataContractSerializer> in <system.runtime.serialization>, om bekende typen te detecteren die zijn toegevoegd via een configuratiebestand.
Verzamelingen die zijn toegewezen aan object
Verzamelingen die zijn toegewezen aan Object, worden geserialiseerd alsof het verzamelingen zijn die worden geïmplementeerd IEnumerable<T>: een JSON-matrix met elke vermelding met een typehint als het een complex type is. Een type Shape
dat is toegewezen, Object ziet er bijvoorbeeld List<T> als volgt uit.
[{"__type":"Shape:#MyApp.Shapes","x":50,"y":70},
{"__type":"Shape:#MyApp.Shapes","x":58,"y":73},
{"__type":"Shape:#MyApp.Shapes","x":41,"y":32}]
Wanneer deserialized terug naar Object:
Shape
moet in de lijst Bekende typen staan. Het hebben List<T> van een typeShape
in bekende typen heeft geen effect. Houd er rekening mee dat u in dit geval niet hoeft toe te voegenShape
aan bekende typen voor serialisatie. Dit wordt automatisch gedaan.De verzameling wordt gedeserialiseerd als een Array type Object dat exemplaren bevat
Shape
.
Afgeleide verzamelingen die zijn toegewezen aan basisverzamelingen
Wanneer een afgeleide verzameling wordt toegewezen aan een basisverzameling, wordt de verzameling meestal geserialiseerd alsof het een verzameling van het basistype was. Als het itemtype van de afgeleide verzameling echter niet kan worden toegewezen aan het itemtype van de basisverzameling, wordt er een uitzondering gegenereerd.
Hints en woordenlijsten typen
Wanneer een woordenlijst wordt toegewezen aan een Object, wordt elke sleutel- en waardevermelding in de woordenlijst behandeld alsof deze is toegewezen Object aan en krijgt een typehint.
Wanneer u woordenlijsttypen serialiseert, wordt het JSON-object dat de leden Sleutel en Waarde bevat, niet beïnvloed door de alwaysEmitTypeInformation
instelling en bevat alleen een typehint wanneer de voorgaande verzamelingsregels dit vereisen.
Geldige JSON-sleutelnamen
De serializer XML-codeert sleutelnamen die geen geldige XML-namen zijn. Een gegevenslid met de naam 123 heeft bijvoorbeeld een gecodeerde naam, zoals '_x0031__x0032__x0033_' omdat '123' een ongeldige XML-elementnaam is (begint met een cijfer). Er kan een vergelijkbare situatie optreden bij sommige internationale tekensets die niet geldig zijn in XML-namen. Zie Toewijzing tussen JSON en XML voor een uitleg van dit effect van XML op JSON-verwerking.