JavaScriptTypeResolver Classe

Définition

Fournit la classe de base abstraite pour implémenter un programme de résolution de type personnalisé.

public ref class JavaScriptTypeResolver abstract
public abstract class JavaScriptTypeResolver
type JavaScriptTypeResolver = class
Public MustInherit Class JavaScriptTypeResolver
Héritage
JavaScriptTypeResolver
Dérivé

Exemples

L’exemple suivant montre comment créer un personnalisé JavaScriptTypeResolver et comment l’utiliser pour sérialiser ou désérialiser un objet.

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’application précédente génère les résultats suivants dans la console, mis en forme pour plus de lisibilité.

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]

Dans l’exemple précédent, le Adult type sous-classe le Person type . Un personnalisé JavaScriptTypeResolver est utilisé pour inclure les informations de type dans le cadre de la charge utile JSON générée. Cela permet un polymorphisme limité lors de la désérialisation de la charge utile JSON dans un graphique d’objets .NET. La charge utile peut contrôler s’il faut renvoyer une instance de base Person ou une instance dérivée Adult à l’appelant.

Cet exemple est sécurisé, car il utilise un allow-list mécanisme pour contrôler la désérialisation. Le code :

  • Initialise le CustomTypeResolver avec une liste explicite des types autorisés.
  • Limite le processus de désérialisation aux seules listes approuvées de types. La restriction empêche les attaques de désérialisation, où le client distant spécifie un malveillant __type dans la charge utile JSON et incite le serveur à désérialiser un type dangereux.

Même si l’application s’attend uniquement à ce Person que les instances et Adult soient désérialisées dans le cadre du tableau de niveau supérieur, il est toujours nécessaire d’ajouter Address à la liste verte pour les raisons suivantes :

  • La sérialisation d’un Person ou Adult sérialise également un Address dans le cadre du graphe d’objets.
  • Tous les types qui peuvent être présents dans le graphique d’objets doivent être pris en compte dans la liste verte. Les primitives aiment int et string n’ont pas besoin d’être spécifiées.

Avertissement

N’appelez Type.GetType(id) pas dans la ResolveType méthode. Cela pourrait introduire une vulnerabilité de sécurité dans l’application. Au lieu de cela, effectuez une itération à travers la liste des types autorisés et comparez leur Type.FullName propriété au entrant id, comme indiqué dans l’exemple précédent.

Remarques

La JavaScriptTypeResolver classe fournit les services pour :

  • Conversion d’informations de type managé en valeur de chaîne via la ResolveTypeId méthode .

  • Résolution d’une valeur de chaîne au type managé approprié via la ResolveType méthode .

Lorsque l’objet JavaScriptSerializer sérialise des types personnalisés, il peut éventuellement inclure dans la chaîne JSON (JavaScript Object Notation) sérialisée une valeur qui contient des informations de type. Pendant la désérialisation, JavaScriptSerializer vous pouvez ensuite référencer cette valeur de chaîne pour déterminer le type managé approprié vers lequel la chaîne JSON sera convertie.

Si vous fournissez un programme de résolution de type à l’instance JavaScriptSerializer , le sérialiseur utilise les ResolveTypeId méthodes et ResolveType pour mapper entre le type managé et la valeur de chaîne pendant le processus de sérialisation et de désérialisation, respectivement.

La JavaScriptTypeResolver classe est la classe de base de la SimpleTypeResolver classe, qui fournit une implémentation d’un programme de résolution de type qui utilise le nom qualifié d’assembly de type managé.

Notes

Lors de l’utilisation d’un JavaScriptTypeResolver, la charge utile JSON résultante contient une propriété spéciale __type . Cette propriété inclut le nom de type complet, y compris l’espace de noms, du type cible. Avant d’utiliser un programme de résolution personnalisé, vérifiez que le nom complet du type cible ne contient pas d’informations sensibles ou privilégiées.

Notes pour les responsables de l’implémentation

Lorsque vous implémentez un programme de résolution de type, la chaîne retournée par la ResolveTypeId(Type) méthode doit être mappée au même type managé lorsque la valeur de chaîne est passée à la ResolveType(String) méthode.

Constructeurs

JavaScriptTypeResolver()

Initialise une nouvelle instance de la classe JavaScriptTypeResolver.

Méthodes

Equals(Object)

Détermine si l'objet spécifié est égal à l'objet actuel.

(Hérité de Object)
GetHashCode()

Fait office de fonction de hachage par défaut.

(Hérité de Object)
GetType()

Obtient le Type de l'instance actuelle.

(Hérité de Object)
MemberwiseClone()

Crée une copie superficielle du Object actuel.

(Hérité de Object)
ResolveType(String)

En cas de substitution dans une classe dérivée, retourne l'objet Type associé au nom du type spécifié.

ResolveTypeId(Type)

En cas de substitution dans une classe dérivée, retourne le nom du type pour l'objet Type spécifié.

ToString()

Retourne une chaîne qui représente l'objet actuel.

(Hérité de Object)

S’applique à