Prendiamo questo esempio: i tipi con nomi di contratto dati "Envelope" e "Point" derivano da un tipo con nome di contratto dati "Geometry". Se "Point" viene inviato da .NET a Javascript e viene quindi restituito ad un metodo .NET che prevede "Geometry", è utile per .NET sapere che l'oggetto in questione è stato originariamente un "Point"; in caso contrario, tutte le informazioni specifiche del tipo derivato (ad esempio i membri dati "x" e "y" su "Point") potrebbero andare perdute.
Per mantenere l'identità del tipo, durante la serializzazione di tipi complessi in JSON, può essere aggiunto un suggerimento; il deserializzatore riconosce tale suggerimento e agisce di conseguenza. Il suggerimento relativo ai tipi è rappresentato da una coppia chiave/valore JSON dove il nome della chiave è "__type" (due caratteri di sottolineatura seguiti dalla parola "type"). Il valore è rappresentato invece da una stringa JSON con forma 'DataContractName:DataContractNamespace' (tutto il testo che precede i due punti rappresenta il nome).
Per ridurre le dimensioni dei messaggi JSON, il prefisso dello spazio dei nomi del contratto dati predefinito viene sostituito dal carattere "#". Per rendere reversibile questa sostituzione, viene utilizzata una regola di escape: se il primo carattere nello spazio dei nomi è "#" o "\", verrà aggiunto un carattere "\"). Pertanto, se "Point" è un tipo nello spazio dei nomi .NET "Studioat.Geometry", il relativo spazio dei nomi del contratto dati sarà: http://schemas.datacontract.org/2004/07/Studioat.Geometry. Le forme e la rappresentazione JSON appaiono nel modo seguente.
//prima forma string a1 = "{\"__type\":\"Point:http:\\/\\/schemas.datacontract.org\\/2004\\/07\\/Studioat.Geometry\",\"X\":10.256,\"Y\":80.729}"; //seconda forma string a2 = "{\"__type\":\"Point:#Studioat.Geometry\",\"X\":10.256,\"Y\":80.729}";
Sia i nomi troncati (#Studioat.Geometry) che quelli completi vengono riconosciuti durante la deserializzazione. Inoltre il suggerimento relativo ai tipi deve essere visualizzato all'inizio nella rappresentazione JSON. Questo è il solo caso in cui l'ordine delle coppie chiave/valore è importante nell'elaborazione di JSON.
Di seguito viene riportato un esempio di modalità non valida per specificare un suggerimento relativo ai tipi.
string a2 = "{\"X\":10.256,\"Y\":80.729,\"__type\":\"Point:#Studioat.Geometry\"}";
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; namespace Studioat.ScratchCode { class Program { static void Main(string[] args) { string a1 = "{\"__type\":\"Point:http:\\/\\/schemas.datacontract.org\\/2004\\/07\\/Studioat.Geometry\",\"X\":10.256,\"Y\":80.729}"; string a2 = "{\"__type\":\"Point:#Studioat.Geometry\",\"X\":10.256,\"Y\":80.729}"; string b1 = "{\"__type\":\"Envelope:http:\\/\\/schemas.datacontract.org\\/2004\\/07\\/Studioat.Geometry\",\"XMin\":10.256,\"YMin\":80.729,\"XMax\":21.956,\"YMax\":34.712}"; string b2 = "{\"__type\":\"Envelope:#Studioat.Geometry\",\"XMin\":10.256,\"YMin\":80.729,\"XMax\":21.956,\"YMax\":34.712}"; byte[] rawstring = System.Text.Encoding.Unicode.GetBytes(a1); MemoryStream stream = new MemoryStream(rawstring); DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Geometry.Geometry), new Type[] { typeof(Geometry.Envelope), typeof(Geometry.Point) }); Geometry.Geometry o = serializer.ReadObject(stream) as Geometry.Geometry; if (o is Geometry.Point) { Geometry.Point j = o as Geometry.Point; Console.WriteLine("Point x:{0} y:{1}", j.X, j.Y); } else if (o is Geometry.Envelope) { Geometry.Envelope j = o as Geometry.Envelope; Console.WriteLine("Envelope xmin:{0} ymin:{1} xmax:{2} ymax:{3}", j.XMin, j.YMin, j.XMax, j.YMax); } Console.Read(); } } } namespace Studioat.Geometry { [DataContract] public abstract class Geometry : ICloneable { protected Geometry() { } public abstract object Clone(); } [DataContract] public class Point : Geometry { private double x; private double y; public Point() { this.x = double.NaN; this.y = double.NaN; } public Point(double x, double y) { this.x = x; this.y = y; } public override object Clone() { Studioat.Geometry.Point point = base.MemberwiseClone() as Studioat.Geometry.Point; return point; } [DataMember] public double X { get; set; } [DataMember] public double Y { get; set; } } [DataContract] public class Envelope : Geometry { private double maxx; private double maxy; private double minx; private double miny; public Envelope() : this(double.NaN, double.NaN, double.NaN, double.NaN) { } public Envelope(Point minPoint, Point maxPoint) : this(minPoint.X, minPoint.Y, maxPoint.X, maxPoint.Y) { } public Envelope(double minx, double miny, double maxx, double maxy) { this.minx = minx; this.miny = miny; this.maxx = maxx; this.maxy = maxy; } public override object Clone() { Envelope envelope = base.MemberwiseClone() as Envelope; return envelope; } [DataMember] public double XMax { get; set; } [DataMember] public double XMin { get; set; } [DataMember] public double YMax { get; set; } [DataMember] public double YMin { get; set; } } }
Nessun commento:
Posta un commento