JavaScriptTypeResolver Classe

Definizione

Fornisce la classe di base astratta per l'implementazione di un resolver di tipi personalizzati.

public ref class JavaScriptTypeResolver abstract
public abstract class JavaScriptTypeResolver
type JavaScriptTypeResolver = class
Public MustInherit Class JavaScriptTypeResolver
Ereditarietà
JavaScriptTypeResolver
Derivato

Esempio

Nell'esempio seguente viene illustrato come creare un oggetto personalizzato JavaScriptTypeResolver e come usarlo per serializzare o deserializzare un oggetto.

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?");
        }
    }
}

L'app precedente restituisce quanto segue nella console, formattata per la leggibilità.

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]

Nell'esempio precedente, la Adult sottoclasse di tipo esegue la sottoclasse del Person tipo. Viene usato un oggetto personalizzato JavaScriptTypeResolver per includere le informazioni sul tipo come parte del payload JSON generato. Ciò consente un polimorfismo limitato durante la deserializzazione del payload JSON in un grafico di oggetti .NET. Il payload può controllare se restituire un'istanza di base Person o un'istanza derivata Adult al chiamante.

Questo esempio è sicuro perché usa un allow-list meccanismo per controllare la deserializzazione. Il codice:

  • Inizializza l'oggetto CustomTypeResolver con un elenco esplicito di tipi consentiti.
  • Limita il processo di deserializzazione solo all'elenco approvato di tipi. La restrizione impedisce attacchi di deserializzazione, in cui il client remoto specifica un dannoso __type nel payload JSON e fa in modo che il server possa deserializzare un tipo pericoloso.

Anche se l'app prevede Person solo la deserializzazione e Adult le istanze come parte della matrice di primo livello, è comunque necessario aggiungere Address all'elenco consentito perché:

  • Serializzazione di un oggetto o Adult serializza anche un PersonAddress oggetto come parte del grafico dell'oggetto.
  • Tutti i tipi che potrebbero essere presenti nel grafico degli oggetti devono essere considerati nell'elenco consenti. Le primitive come int e string non devono essere specificate.

Avviso

Non chiamare Type.GetType(id) all'interno del ResolveType metodo. Ciò potrebbe introdurre una vunerability di sicurezza nell'app. Scorrere invece l'elenco di tipi consentiti e confrontare la proprietà Type.FullName rispetto all'oggetto in ingresso id, come illustrato nell'esempio precedente.

Commenti

La JavaScriptTypeResolver classe fornisce i servizi per:

  • Conversione di informazioni sul tipo gestito in un valore stringa tramite il ResolveTypeId metodo .

  • Risoluzione di un valore stringa al tipo gestito appropriato tramite il ResolveType metodo .

Quando l'oggetto JavaScriptSerializer serializza tipi personalizzati, può includere facoltativamente nella stringa JavaScript Object Notation (JSON) serializzata un valore che contiene informazioni sul tipo. Durante la deserializzazione, JavaScriptSerializer può quindi fare riferimento a questo valore stringa per determinare il tipo gestito appropriato a cui verrà convertita la stringa JSON.

Se si specifica un resolver di tipo all'istanza JavaScriptSerializer , il serializzatore userà rispettivamente i ResolveTypeId metodi e ResolveType per eseguire il mapping tra il tipo gestito e il valore stringa durante il processo di serializzazione e deserializzazione.

La JavaScriptTypeResolver classe è la classe di base per la classe, che fornisce un'implementazione di un resolver di tipo che usa il nome qualificato dell'assembly SimpleTypeResolver di tipo gestito.

Nota

Quando si usa un JavaScriptTypeResolverpayload JSON risultante contiene una proprietà speciale __type . Questa proprietà include il nome completo del tipo, incluso lo spazio dei nomi, del tipo di destinazione. Prima di usare un resolver personalizzato, verificare che il nome completo del tipo di destinazione non contenga informazioni sensibili o con privilegi.

Note per gli implementatori

Quando si implementa un resolver di tipo, la stringa restituita dal ResolveTypeId(Type) metodo deve eseguire il mapping allo stesso tipo gestito quando il valore stringa viene passato al ResolveType(String) metodo.

Costruttori

JavaScriptTypeResolver()

Inizializza una nuova istanza della classe JavaScriptTypeResolver.

Metodi

Equals(Object)

Determina se l'oggetto specificato è uguale all'oggetto corrente.

(Ereditato da Object)
GetHashCode()

Funge da funzione hash predefinita.

(Ereditato da Object)
GetType()

Ottiene l'oggetto Type dell'istanza corrente.

(Ereditato da Object)
MemberwiseClone()

Crea una copia superficiale dell'oggetto Object corrente.

(Ereditato da Object)
ResolveType(String)

Se sottoposto a override in una classe derivata, restituisce l'oggetto Type associato al nome del tipo specificato.

ResolveTypeId(Type)

Se sottoposto a override in una classe derivata, restituisce il nome del tipo per l'oggetto Type specificato.

ToString()

Restituisce una stringa che rappresenta l'oggetto corrente.

(Ereditato da Object)

Si applica a