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 允许类型的显式列表初始化。
  • 将反序列化过程限制为仅批准的类型列表。 此限制可防止 反序列化攻击,其中远程客户端在 JSON 有效负载中指定恶意 __type ,并诱使服务器反序列化危险类型。

尽管应用只期望 PersonAdult 实例作为顶级数组的一部分进行反序列化,但仍需要添加到 Address 允许列表,因为:

  • 序列化 PersonAdult 同时序列化对象图中的一 Address 部分。
  • 对象图中可能存在的所有类型都需要在允许列表中考虑。 基元类似 intstring 不需要指定。

Warning

不要在ResolveType方法中调用Type.GetType(id)。 这可能会将安全 vunerability 引入应用。 而是循环访问允许的类型列表,并将其 Type.FullName 属性与传入 id进行比较,如前面的示例所示。

注解

JavaScriptTypeResolver 类提供以下服务的服务:

  • 通过 ResolveTypeId 该方法将托管类型信息转换为字符串值。

  • 通过 ResolveType 该方法将字符串值解析回适当的托管类型。

JavaScriptSerializer当对象序列化自定义类型时,它可以选择性地包含在序列化的 JavaScript 对象表示法(JSON)字符串中,该值包含类型信息。 在反序列化期间, JavaScriptSerializer 可以引用此字符串值来确定将 JSON 字符串转换为的相应托管类型。

如果向实例提供类型解析程序 JavaScriptSerializer ,序列化程序将分别在序列化和反序列化过程中使用 ResolveTypeId 托管类型和字符串值之间的映射和 ResolveType 方法。

JavaScriptTypeResolver 类是类的 SimpleTypeResolver 基类,该类提供使用托管类型程序集限定名称的类型解析程序的实现。

Note

使用 a 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)

适用于