JavaScriptTypeResolver 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
提供用于实现自定义类型解析程序的抽象基类。
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,并诱使服务器反序列化危险类型。
尽管应用只期望 Person 和 Adult 实例作为顶级数组的一部分进行反序列化,但仍需要添加到 Address 允许列表,因为:
- 序列化
Person或Adult同时序列化对象图中的一Address部分。 - 对象图中可能存在的所有类型都需要在允许列表中考虑。 基元类似
int且string不需要指定。
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) |