JavaScriptTypeResolver Класс

Определение

Предоставляет абстрактный базовый класс для реализации распознавателя пользовательских типов.

public ref class JavaScriptTypeResolver abstract
public abstract class JavaScriptTypeResolver
type JavaScriptTypeResolver = class
Public MustInherit Class JavaScriptTypeResolver
Наследование
JavaScriptTypeResolver
Производный

Примеры

В следующем примере показано, как создать пользовательский JavaScriptTypeResolver объект и как использовать его для сериализации или десериализации объекта.

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

Предыдущее приложение выводит в консоль следующую информацию, отформатированную для удобства чтения.

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]

В предыдущем примере тип относится к Adult подклассам Person типа . Настраиваемый JavaScriptTypeResolver используется для включения сведений о типе в состав созданных полезных данных JSON. Это обеспечивает ограниченный полиморфизм при десериализации полезных данных JSON обратно в граф объектов .NET. Полезные данные могут управлять возвратом базового Person или производного Adult экземпляра вызывающей стороне.

Этот пример безопасен, так как использует allow-list механизм для управления десериализацией. Код.

  • Инициализирует с CustomTypeResolver явным списком разрешенных типов.
  • Ограничивает процесс десериализации только утвержденным списком типов. Ограничение предотвращает атаки десериализации, когда удаленный клиент указывает вредоносный __type объект в полезных данных JSON и обманывает сервер для десериализации опасного типа.

Несмотря на то, что приложение ожидает десериализации Person только экземпляров и Adult как часть массива верхнего уровня, по-прежнему необходимо добавить Address в список разрешений, так как:

  • Сериализация Person или Adult также сериализует Address как часть графа объектов.
  • Все типы, которые могут присутствовать в графе объектов, должны быть учтены в списке разрешений. Примитивы, такие как int и string , указывать не нужно.

Предупреждение

Не вызывайте Type.GetType(id) в методе ResolveType . Это может привести к обеспечению безопасности в приложении. Вместо этого выполните итерацию по списку разрешенных типов и сравните их Type.FullName свойство с входящим id, как показано в предыдущем примере.

Комментарии

Класс JavaScriptTypeResolver предоставляет службы для:

  • Преобразование сведений об управляемом типе в строковое значение с помощью ResolveTypeId метода .

  • Разрешение строкового значения обратно в соответствующий управляемый ResolveType тип с помощью метода .

JavaScriptSerializer Когда объект сериализует пользовательские типы, он может при необходимости включить в сериализованную строку нотации объектов JavaScript (JSON) значение, содержащее сведения о типе. Во время десериализации может ссылаться на это строковое значение, чтобы определить соответствующий управляемый тип, JavaScriptSerializer в который будет преобразована строка JSON.

Если предоставить сопоставитель типов для экземпляра JavaScriptSerializer , сериализатор будет использовать ResolveTypeId методы и ResolveType для сопоставления между управляемым типом и строковым значением в процессе сериализации и десериализации соответственно.

Класс JavaScriptTypeResolver является базовым классом SimpleTypeResolver для класса , который предоставляет реализацию сопоставителя типов, использующего имя управляемого типа с указанием сборки.

Примечание

При использовании JavaScriptTypeResolverрезультирующая полезные данные JSON содержит специальное __type свойство . Это свойство включает полное имя типа, включая пространство имен, целевого типа. Перед использованием пользовательского сопоставителя убедитесь, что полное имя целевого типа не содержит конфиденциальных или привилегированных сведений.

Примечания для тех, кто реализует этот метод

При реализации сопоставителя типов строка, возвращаемая методом , должна сопоставляться с тем же управляемым типом ResolveTypeId(Type) при передаче строкового значения в ResolveType(String) метод .

Конструкторы

JavaScriptTypeResolver()

Инициализирует новый экземпляр класса JavaScriptTypeResolver.

Методы

Equals(Object)

Определяет, равен ли указанный объект текущему объекту.

(Унаследовано от Object)
GetHashCode()

Служит хэш-функцией по умолчанию.

(Унаследовано от Object)
GetType()

Возвращает объект Type для текущего экземпляра.

(Унаследовано от Object)
MemberwiseClone()

Создает неполную копию текущего объекта Object.

(Унаследовано от Object)
ResolveType(String)

При переопределении в производном классе возвращает объект Type, связанный с указанным именем типа.

ResolveTypeId(Type)

При переопределении в производном классе возвращает имя типа для указанного объекта Type.

ToString()

Возвращает строку, представляющую текущий объект.

(Унаследовано от Object)

Применяется к