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)。 這可能會為應用程式帶來安全漏洞。 相反地,依序遍歷允許的類型清單,並將其性質 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)

適用於