Sdílet prostřednictvím


JavaScriptTypeResolver Třída

Definice

Poskytuje abstraktní základní třídu pro implementaci vlastního překladače typů.

public ref class JavaScriptTypeResolver abstract
public abstract class JavaScriptTypeResolver
type JavaScriptTypeResolver = class
Public MustInherit Class JavaScriptTypeResolver
Dědičnost
JavaScriptTypeResolver
Odvozené

Příklady

Následující příklad ukazuje, jak vytvořit vlastní JavaScriptTypeResolver a jak jej použít k serializaci nebo deserializaci objektu.

using System;
using System.Linq;
using System.Web.Script.Serialization;

namespace SampleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // The object array to serialize.
            Person[] people = new Person[]
            {
                new Person()
                {
                    Name = "Kristen Solstad",
                    Age = 15,
                    HomeAddress = new Address()
                    {
                        Street1 = "123 Palm Ave",
                        City = "Some City",
                        StateOrProvince = "ST",
                        Country = "United States",
                        PostalCode = "00000"
                    }
                },
                new Adult()
                {
                    Name = "Alex Johnson",
                    Age = 39,
                    Occupation = "Mechanic",
                    HomeAddress = new Address()
                    {
                        Street1 = "445 Lorry Way",
                        Street2 = "Unit 3A",
                        City = "Some City",
                        Country = "United Kingdom",
                        PostalCode = "AA0 A00"
                    }
                }
            };

            // Serialize the object array, then write it to the console.
            string serializedData = SerializePeopleArray(people);
            Console.WriteLine("Serialized:");
            Console.WriteLine(serializedData);
            Console.WriteLine();

            // Now deserialize the object array.
            Person[] deserializedArray = DeserializePeopleArray(serializedData);
            Console.WriteLine("Deserialized " + deserializedArray.Length + " people.");
            foreach (Person person in deserializedArray)
            {
                Console.WriteLine(person.Name + " (Age " + person.Age + ") [" + person.GetType() + "]");
            }
        }

        static string SerializePeopleArray(Person[] people)
        {
            // The custom type resolver to use.
            // Note: Except for primitives like int and string, *every* type that
            // we might see in the object graph must be listed here.
            CustomTypeResolver resolver = new CustomTypeResolver(
                typeof(Person),
                typeof(Adult),
                typeof(Address));

            // Instantiate the serializer.
            JavaScriptSerializer serializer = new JavaScriptSerializer(resolver);

            // Serialize the object array, then return it.
            string serialized = serializer.Serialize(people);
            return serialized;
        }

        static Person[] DeserializePeopleArray(string serializedData)
        {
            // The custom type resolver to use.
            // Note: This is the same list that was provided to the Serialize routine.
            CustomTypeResolver resolver = new CustomTypeResolver(
                typeof(Person),
                typeof(Adult),
                typeof(Address));

            // Instantiate the serializer.
            JavaScriptSerializer serializer = new JavaScriptSerializer(resolver);

            // Deserialize the object array, then return it.
            Person[] deserialized = serializer.Deserialize<Person[]>(serializedData);
            return deserialized;
        }
    }

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Address HomeAddress { get; set; }
    }

    public class Adult : Person
    {
        public string Occupation { get; set; }
    }

    public class Address
    {
        public string Street1 { get; set; }
        public string Street2 { get; set; }
        public string City { get; set; }
        public string StateOrProvince { get; set; }
        public string Country { get; set; }
        public string PostalCode { get; set; }
    }

    // A custom JavaScriptTypeResolver that restricts the payload
    // to a set of known good types.
    class CustomTypeResolver : JavaScriptTypeResolver
    {
        private readonly Type[] _allowedTypes;

        public CustomTypeResolver(params Type[] allowedTypes)
        {
            if (allowedTypes == null)
            {
                throw new ArgumentNullException("allowedTypes");
            }

            // Make a copy of the array the caller gave us.
            _allowedTypes = (Type[])allowedTypes.Clone();
        }

        public override Type ResolveType(string id)
        {
            // Iterate over all of the allowed types, looking for a match
            // for the 'id' parameter. Calling Type.GetType(id) is dangerous,
            // so we instead perform a match on the Type.FullName property.
            foreach (Type allowedType in _allowedTypes)
            {
                if (allowedType.FullName == id)
                {
                    return allowedType;
                }
            }

            // The caller provided a type we don't recognize. This could be
            // dangerous, so we'll fail the operation immediately.
            throw new ArgumentException("Unknown type: " + id, "id");
        }

        public override string ResolveTypeId(Type type)
        {
            // Before we serialize data, quickly double-check to make
            // sure we're allowed to deserialize the data. Otherwise it's
            // no good serializing something if we can't deserialize it.
            if (_allowedTypes.Contains(type))
            {
                return type.FullName;
            }

            throw new InvalidOperationException("Cannot serialize an object of type " + type + ". Did you forget to add it to the allow list?");
        }
    }
}

Předchozí aplikace vypíše do konzoly následující text, který je naformátovaný pro lepší čitelnost.

Serialized:
[
    {
        "__type": "SampleApp.Person",
        "Name": "Kristen Solstad",
        "Age": 15,
        "HomeAddress": {
            "__type": "SampleApp.Address",
            "Street1": "123 Palm Ave",
            "Street2": null,
            "City": "Some City",
            "StateOrProvince": "ST",
            "Country": "United States",
            "PostalCode": "00000"
        }
    },
    {
        "__type": "SampleApp.Adult",
        "Occupation": "Mechanic",
        "Name": "Alex Johnson",
        "Age": 39,
        "HomeAddress": {
            "__type": "SampleApp.Address",
            "Street1": "445 Lorry Way",
            "Street2": "Unit 3A",
            "City": "Some City",
            "StateOrProvince": null,
            "Country": "United Kingdom",
            "PostalCode": "AA0 A00"
        }
    }
]

Deserialized 2 people.
Kristen Solstad (Age 15) [SampleApp.Person]
Alex Johnson (Age 39) [SampleApp.Adult]

V předchozí ukázce Adult typ podtřídy Person typ. Vlastní JavaScriptTypeResolver se používá k zahrnutí informací o typu jako součást vygenerované datové části JSON. To umožňuje omezený polymorfismus při deserializaci datové části JSON zpět do grafu objektů .NET. Datová část může řídit, zda se má vrátit základní Person instance nebo odvozená Adult instance zpět volajícímu.

Tato ukázka je bezpečná, protože používá allow-list mechanismus pro řízení deserializace. Kód:

  • Inicializuje s CustomTypeResolver explicitním seznamem povolených typů.
  • Omezuje proces deserializace pouze na seznam schválených typů. Omezení brání útokům na deserializaci, kdy vzdálený klient určí v datové části JSON škodlivý __type objekt a ošidí server k deserializaci nebezpečného typu.

I když aplikace očekává, že Person instance a Adult budou deserializovány pouze jako součást pole nejvyšší úrovně, je stále nutné přidat Address do seznamu povolených, protože:

  • Serializace Person nebo Adult také serializuje Address jako součást grafu objektu.
  • Všechny typy, které můžou být v grafu objektů, je potřeba zohlednit v seznamu povolených. Primitiva jako int a string není nutné zadávat.

Upozornění

Nevolejte Type.GetType(id) v rámci ResolveType metody . To by mohlo do aplikace zavést odolnost zabezpečení. Místo toho iterujte seznamem povolených typů a porovnejte jejich Type.FullName vlastnosti s příchozím idobjektem , jak je znázorněno v předchozí ukázce.

Poznámky

Třída JavaScriptTypeResolver poskytuje služby pro:

  • Převod informací o spravovaném typu na řetězcovou hodnotu pomocí metody .ResolveTypeId

  • Překlad řetězcové hodnoty zpět na příslušný spravovaný typ prostřednictvím ResolveType metody .

JavaScriptSerializer Když objekt serializuje vlastní typy, může volitelně zahrnout do serializovaného řetězce JSON (JavaScript Object Notation) hodnotu, která obsahuje informace o typu. Během deserializace pak může odkazovat na tuto řetězcovou hodnotu a určit odpovídající spravovaný typ, JavaScriptSerializer na který se řetězec JSON převede.

Pokud poskytnete překladač JavaScriptSerializer typu instance serializátor bude používat ResolveTypeId metody a ResolveType k mapování mezi spravovaným typem a řetězcovou hodnotou během procesu serializace a deserializace, v uvedeném pořadí.

Třída JavaScriptTypeResolver je základní třídou pro SimpleTypeResolver třídu, která poskytuje implementaci překladače typů, který používá název kvalifikovaný pro sestavení spravovaného typu.

Poznámka

Při použití objektu JavaScriptTypeResolverobsahuje výsledná datová část JSON speciální __type vlastnost. Tato vlastnost zahrnuje úplný název typu, včetně oboru názvů, cílového typu. Před použitím vlastního překladače ověřte, že úplný název cílového typu neobsahuje citlivé nebo privilegované informace.

Poznámky pro implementátory

Při implementaci překladače typů musí být řetězec vrácený metodou ResolveTypeId(Type) mapován zpět na stejný spravovaný typ, pokud je hodnota řetězce předána ResolveType(String) metodě.

Konstruktory

JavaScriptTypeResolver()

Inicializuje novou instanci JavaScriptTypeResolver třídy .

Metody

Equals(Object)

Určí, zda se zadaný objekt rovná aktuálnímu objektu.

(Zděděno od Object)
GetHashCode()

Slouží jako výchozí hashovací funkce.

(Zděděno od Object)
GetType()

Type Získá z aktuální instance.

(Zděděno od Object)
MemberwiseClone()

Vytvoří mělkou kopii aktuálního Objectsouboru .

(Zděděno od Object)
ResolveType(String)

Při přepsání v odvozené třídě vrátí Type objekt, který je přidružen k zadanému názvu typu.

ResolveTypeId(Type)

Při přepsání v odvozené třídě vrátí název typu pro zadaný Type objekt.

ToString()

Vrátí řetězec, který představuje aktuální objekt.

(Zděděno od Object)

Platí pro