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 允許清單,因為:
- 序列化 或
PersonAdult同時序列化 ,將 序列Address化為物件圖的一部分。 - 物件圖中可能存在的所有類型都需要納入允許清單。 喜歡
int和string的原元不需要特別指定。
Warning
請勿在系統內ResolveType打電話Type.GetType(id)。 這可能會為應用程式帶來安全漏洞。 相反地,依序遍歷允許的類型清單,並將其性質 Type.FullName 與前述範例所示的 與輸入 id的 比較。
備註
該 JavaScriptTypeResolver 班級提供以下服務:
透過此 ResolveTypeId 方法將受管理型態資訊轉換為字串值。
透過方法 ResolveType 將字串值解析回適當的管理型別。
當 JavaScriptSerializer 物件序列化自訂型別時,可以選擇性地在序列化的 JavaScript 物件符號(JSON)字串中包含包含型別資訊的值。 在反序列化過程中, JavaScriptSerializer 可以參考這個字串值,以決定 JSON 字串將被轉換成的適當管理型別。
如果你為實例提供型別解析器 JavaScriptSerializer ,序列化器會在序列化和反序列化過程中,分別使用 ResolveTypeId and ResolveType 方法在管理型別與字串值之間對應。
該 JavaScriptTypeResolver 類別是該 SimpleTypeResolver 類別的基底類別,提供使用受管理型別組合語言限定名稱的型別解析器實作。
Note
當使用 時 JavaScriptTypeResolver,所得的 JSON 有效載荷包含一個特殊 __type 屬性。 此屬性包含目標型態的完整型別名稱,包括命名空間。 在使用自訂解析器前,請確認目標型態的全名中沒有敏感或特權資訊。
給實施者的注意事項
當你實作型別解析器時,當字串值傳給ResolveType(String)方法時,方法回傳ResolveTypeId(Type)的字串必須映射回相同的管理型別。
建構函式
| 名稱 | Description |
|---|---|
| JavaScriptTypeResolver() |
初始化 JavaScriptTypeResolver 類別的新執行個體。 |
方法
| 名稱 | Description |
|---|---|
| Equals(Object) |
判斷指定的 物件是否等於目前的物件。 (繼承來源 Object) |
| GetHashCode() |
做為預設雜湊函式。 (繼承來源 Object) |
| GetType() |
取得目前實例的 Type。 (繼承來源 Object) |
| MemberwiseClone() |
建立目前 Object的淺層複本。 (繼承來源 Object) |
| ResolveType(String) |
當在衍生類別中覆寫時,會回傳 Type 與指定型別名稱相關的物件。 |
| ResolveTypeId(Type) |
當在衍生類別中覆寫時,會回傳指定 Type 物件的型別名稱。 |
| ToString() |
傳回表示目前 物件的字串。 (繼承來源 Object) |