JavaScriptTypeResolver Classe

Definição

Fornece a classe base abstrata para implementar um resolvedor de tipo personalizado.

public ref class JavaScriptTypeResolver abstract
public abstract class JavaScriptTypeResolver
type JavaScriptTypeResolver = class
Public MustInherit Class JavaScriptTypeResolver
Herança
JavaScriptTypeResolver
Derivado

Exemplos

O exemplo a seguir mostra como criar um personalizado JavaScriptTypeResolver e como usá-lo para serializar ou desserializar um objeto.

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

O aplicativo anterior gera o seguinte para o console, formatado para legibilidade.

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]

No exemplo anterior, o Adult tipo subclasse o Person tipo. Um personalizado JavaScriptTypeResolver é usado para incluir as informações de tipo como parte do conteúdo JSON gerado. Isso permite polimorfismo limitado ao desserializar a carga JSON de volta em um grafo de objeto .NET. O conteúdo pode controlar se uma instância base Person ou uma instância derivada deve ser retornada Adult ao chamador.

Este exemplo é seguro porque usa um allow-list mecanismo para controlar a desserialização. O código:

  • Inicializa com CustomTypeResolver uma lista explícita de tipos permitidos.
  • Restringe o processo de desserialização a apenas uma lista de tipos aprovados. A restrição impede ataques de desserialização, em que o cliente remoto especifica um mal-intencionado __type no conteúdo JSON e engana o servidor para desserializar um tipo perigoso.

Embora o aplicativo só espere Person e Adult as instâncias sejam desserializadas como parte da matriz de nível superior, ainda é necessário adicionar Address à lista de permissões porque:

  • Serializar um Person ou Adult também serializa um Address como parte do grafo de objeto.
  • Todos os tipos que podem estar presentes no grafo de objeto precisam ser contabilizados na lista de permissões. Primitivos gostam int e string não precisam ser especificados.

Aviso

Não chame Type.GetType(id) dentro do ResolveType método. Isso pode introduzir uma vunerabilidade de segurança no aplicativo. Em vez disso, itere pela lista de tipos permitidos e compare sua Type.FullName propriedade com a entrada id, conforme mostrado no exemplo anterior.

Comentários

A JavaScriptTypeResolver classe fornece os serviços para:

  • Convertendo informações de tipo gerenciado em um valor de cadeia de caracteres por meio do ResolveTypeId método.

  • Resolvendo um valor de cadeia de caracteres de volta para o tipo gerenciado apropriado por meio do ResolveType método.

Quando o JavaScriptSerializer objeto serializa tipos personalizados, ele pode incluir opcionalmente na cadeia de caracteres JSON (JavaScript Object Notation) serializada um valor que contém informações de tipo. Durante a desserialização, JavaScriptSerializer pode referenciar esse valor de cadeia de caracteres para determinar o tipo gerenciado apropriado para o qual a cadeia de caracteres JSON será convertida.

Se você fornecer um resolvedor de tipo para a JavaScriptSerializer instância, o serializador usará o e ResolveType os ResolveTypeId métodos para mapear entre o tipo gerenciado e o valor da cadeia de caracteres durante o processo de serialização e desserialização, respectivamente.

A JavaScriptTypeResolver classe é a classe base da SimpleTypeResolver classe, que fornece uma implementação de um resolvedor de tipo que usa o nome qualificado para assembly do tipo gerenciado.

Note

Ao usar um JavaScriptTypeResolverconteúdo JSON resultante contém uma propriedade especial __type . Essa propriedade inclui o nome de tipo completo, incluindo o namespace, do tipo de destino. Antes de usar um resolvedor personalizado, verifique se o nome completo do tipo de destino não contém informações confidenciais ou privilegiadas.

Notas aos Implementadores

Quando você implementa um resolvedor de tipo, a cadeia de caracteres retornada pelo ResolveTypeId(Type) método deve ser mapeada de volta para o mesmo tipo gerenciado quando o valor da cadeia de caracteres é passado para o ResolveType(String) método.

Construtores

Nome Description
JavaScriptTypeResolver()

Inicializa uma nova instância da classe JavaScriptTypeResolver.

Métodos

Nome Description
Equals(Object)

Determina se o objeto especificado é igual ao objeto atual.

(Herdado de Object)
GetHashCode()

Serve como a função hash predefinida.

(Herdado de Object)
GetType()

Obtém o Type da instância atual.

(Herdado de Object)
MemberwiseClone()

Cria uma cópia superficial do Objectatual.

(Herdado de Object)
ResolveType(String)

Quando substituído em uma classe derivada, retorna o Type objeto associado ao nome de tipo especificado.

ResolveTypeId(Type)

Quando substituído em uma classe derivada, retorna o nome do tipo para o objeto especificado Type .

ToString()

Retorna uma cadeia de caracteres que representa o objeto atual.

(Herdado de Object)

Aplica-se a