Json .Net for Unity 2.0.1

之前說過继谚,JSON .NET For Unity具有比JsonFx For Unity3D更好的平臺兼容性焰盗,所以這一系列主要簡單介紹一下這個插件缰盏。
下面先把內置幫助文檔翻譯一下迫横,方便之后的查詢和學習谓谦。(全部機翻统扳,在一些細節(jié)方面做了略微調整)

Introduction

Overview

Json .Net unity 是官方 Json .Net 庫的端口喘帚。 它創(chuàng)建的目的是將 Json .Net 的強大功能引入 Unity,因為官方庫與大多數(shù) Unity 平臺不兼容,并且與使用 IL2CPP 構建的任何平臺不兼容畅姊。 本文檔的目的是為 Unity 開發(fā)人員提供清晰的使用示例和技術說明,并且應該很容易理解您是新手還是經驗豐富的開發(fā)人員。 它沒有詳細說明 Json .Net 的每個功能吹由。 全面的文檔可以在正式的 Json .Net 幫助頁面上找到若未。

由于官方 Json .Net 不支持 Unity,因此應向我們發(fā)送與此資產相關的任何問題。

Changes From Previous Versions

Json .Net 為 Unity 2.0 中有一些重要更改倾鲫。 目前,我們不再支持 Unity 5 之前的 Unity 版本粗合。 這是一個設計決策,使資產保持清潔。 Unity 的早期版本不允許將 DLL 映射到不同的目標平臺乌昔。 這意味著 Json .Net for Unity 必須作為完整源代碼包含在項目中,因為它嚴重依賴編譯器指令來為每個目標平臺編譯正確的代碼舌劳。

此外,這種方法使得支持新平臺變得極其困難。 Json .Net for Unity 以前基于 Json .Net 的舊版本 (4.x), 錯誤修復和修改隨著時間的推移進行了修補玫荣。 這使得更新配置文件極其困難,這也意味著為了支持新的平臺,必須移植Json .Net的完整新版本,這是WinRT文件夾的原因(它實際上是Json .Net的完全不同的版本)甚淡。

自 2.0 版起,Json .Net for Unity 正在更好地利用分支策略。 它開始與一個干凈的石板,和一個全新的干凈的克隆從官方存儲庫捅厂。 官方存儲庫中的 Bug 修復可以更輕松地遷移到 Json .Net for Unity,而 Unity 的特定增強功能可以繼續(xù)進行贯卦。

源代碼仍包含在 .zip 存檔中。 此代碼包括一個 Visual Studio 解決方案,該解決方案將單個代碼庫劃分為多個項目焙贷。 本文檔稍后將對此進行詳細討論撵割。

此外,我們還刪除了對 WebPlayer 的支持,因為它已被 Unity 棄用,并且在大多數(shù)現(xiàn)代瀏覽器中不再受支持,并且暫時刪除了對 Windows Phone 8.1 的支持,轉而支持 Windows 10 UWP。

Limitations

不支持在 Unity 對象中構建的某些對象辙芍。 其中包括游戲對象和從單行為繼承的任何內容啡彬。 有幾個原因。 直接序列化游戲對象時,實用程序有限,因為

你不能簡單地new起來故硅。 它們需要通過instiantiating來添加到場景中庶灿。 因此,您無法反序列化。 這也是維護父/子關系所必需的吃衅。 Unity 還會重載部分對象的等號檢查 (==operate),因此即使它們實際上不是,它們也假設為 null往踢。 一些屬性(如rigidbody)已被棄用,但它們通過反射可見,當序列化程序嘗試序列化的時候將導致 Unity 引發(fā)異常。 您可以創(chuàng)建自己的代理類來序列化這些類,但是,一旦實例化它們,就可以重新填充它們徘层。

Installation

自 2.0 版起,聯(lián)合體 Json .Net 的結構已更改峻呕。 此更改提供了更簡潔的文件夾結構,減少了"noise",并且更易于識別和使用。 由于 Unity 目標平臺之間的 API 差異,資產被編譯為多個 DLL趣效。 這些 DLL 映射到各種平臺目標瘦癌。

始終建議您在導入新版本之前刪除現(xiàn)有的 /JsonDotNet 文件夾。 這可確保獲得干凈的版本跷敬。 導入新包后,您將具有以下文件夾結構:

1.png

除了壓縮的源和程序集外,Json .Net for Unity 還包括其自己的 link.xml 文件讯私。 此文件用于防止 Unity 剝離 Json .Net 使用的類中內置的類。 當發(fā)現(xiàn)新的剝離問題時,此文件將更新。 如果要添加自己的項目,建議您在 /JsonDotNet 文件夾之外的 link.xml 文件中添加項目,以確保在更新資產時不會覆蓋這些項目妄帘。

最后,Json .Net 的目標文件夾并不重要楞黄。 您可以將資產移動到任何需要文件夾。 只需確保鏈接.xml 文件被保留抡驼。 如果從 Unity 外部移動文件,還需要將 DLL 重新映射到相應的平臺鬼廓。 本文檔末尾有一個映射指南,可幫助您將 DLL 映射到正確的目標平臺。

Consoles and Other Unmapped Platforms

控制臺和大多數(shù)其他未映射的平臺支持開箱即用,但它們需要訪問其各自的 SDK 和專用 Unity 構建,以便為平臺映射相應的 DLL致盟。 對于所有控制臺(和幾乎所有其他情況),這些平臺應映射到/JsonDotNet/Assemblies/Aot/Newtonsoft.Json.dll 文件碎税。 要映射此文件,請在檢查器中選擇 DLL。 在平臺列表中查找正確的平臺并選擇它馏锡。 某些平臺需要"占位符"DLL,用于

編輯器和預構建雷蹂。 如果存在占位符選項,請單擊下拉列表并選擇 .。/組件/獨立/牛頓軟.Json.dll 組件杯道。 單擊"應用",您應該可以進行構建匪煌。

如有疑問,請參閱本文檔末尾的平臺 DLL 映射指南。 如果您在使用特定平臺時遇到問題,請聯(lián)系我們,我們將很樂意為您提供幫助党巾。

Unsupported Platforms

Json .Net unity 不支持傳統(tǒng)的 Unity 平臺,如黑莓或閃存萎庭。 自 2.0 版起,我們也不再支持 Webplayer、Windows 8.0 或 Windows Phone 8.0齿拂。 8.1 SDK 支持 Windows 8.1 和 8.1 通用版本驳规。 此版本當前不支持開箱即用的 Windows Phone 8.1。如有必要,可以為其創(chuàng)建生成署海。

Working with the Defaults

Modifying Default Serialization Settings

默認情況下,大多數(shù)人只會執(zhí)行其序列化,而不指定 Json 序列化設置的自定義實例吗购。 發(fā)生這種情況時,Json .Net 使用默認配置。 您可以獲取此配置(甚至重寫生成它的函數(shù)),并更改默認情況下 Json .Net 行為方式砸狞。

靜態(tài) JsonConvert 類包含一個稱為 DefaultSettings 的方法捻勉。 這將返回 Json 序列化程序設置的實例。 更改通過此方法獲得的類上的設置將更改 Json .Net 的默認行為,并將影響對不提供自定義設置的序列化對象和反序列化對象的所有調用趾代。 本文檔后面的"Providing Custom Serialization Settings"部分提供了最常見的可用選項及其操作的列表贯底。

Built-in Json Converters

Json .Net 本身附帶多個內置轉換器,如 StringEnum 轉換器,它處理枚舉的序列化和反序列化作為字符串,而不是其整數(shù)值和 IsoDateTime 轉換器,用于處理日期和從Iso 日期時間格式。 這些轉換器是可選的,我們討論了它們在使用轉換器的序列化和反序列化部分中的用法撒强。

除了官方轉換器,Json .Net 為 Unity 附帶了一些 Unity 特定轉換器。 其中包括矢量轉換器笙什、矩陣4x4轉換器飘哨、分辨率轉換器、哈希集轉換器和色變器,因為這些是常見項目琐凭。 默認情況下,矢量轉換器和哈希集轉換器處于啟用狀態(tài),并且在創(chuàng)建 Json 序列器設置的新實例時已位于轉換器集合中(稍后將對此進行介紹)芽隆。 如果您愿意,它們可能會被刪除并替換為您自己的。 由于 Unity 錯誤,需要哈希設置轉換器在 AOT 平臺上正確實現(xiàn)哈希設置反序列化。

內置轉換器具有以下幾個用途胚吁。 它們僅通過序列化數(shù)據(jù)屬性來簡化生成的 json牙躺。 也就是說,它們不序列化計算屬性。 例如,Vector 轉換器將僅序列化 Vector2腕扶、Vector3 和 Vector4 的 x孽拷、y、z 和 w 屬性半抱。 它們還可以提高序列化和反序列化這些常見類型時的性能,因為它們能夠快速生成 json 或將 json 轉換為適當?shù)膶ο?而無需使用額外的反射來解決屬性脓恕。

某些轉換器還提供其他自定義。 例如,VectorConverter 被構建為單個轉換器,用于處理 Vector2窿侈、Vector3 和 Vector4 類型炼幔。 您可以將默認設置中的矢量轉換器替換為新實例,或修改現(xiàn)有實例的屬性。 它包含一個重載構造函數(shù),該構造函數(shù)接受 3 個布爾參數(shù),指定是否應分別用于 Vector2史简、Vector3 和/或 Vector4乃秀。
Vector 轉換器的簽名如下所示:

public VectorConverter(bool enableVector2, bool enableVector3, bool enableVector4) 

它還包含匹配的啟用Vector2、啟用Vector3和啟用Vector4屬性圆兵。 將任何這些設置為 false 將導致轉換器未用于該類型环形。 請記住,某些類型(如 Vectors)至少需要某種轉換器,因為它們的計算屬性也返回 Vector,從而導致無限深度序列化,這將導致異常。

Serializing and Deserializing Data

Basic Serialization and Deserialization

Json .Net for Unity 可處理最常見的開箱即用方案衙傀。 這項工作的核心由 JsonConvert 類的靜態(tài)序列化對象和反序列化對象方法執(zhí)行抬吟。 假設我們有以下枚舉和類:

        public enum CharacterType
        {
            Oger = 10,
            Human = 20,
            Orc = 30,
            Elf = 40
        }

        public class PlayerInfo
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public CharacterType Race { get; set; }
        }

我們可以創(chuàng)建一個新的實例,通過調用 JsonConvert.SerializeObject(實例)來序列化此類。

        var mainPlayer = new PlayerInfo() { Name = "Dustin", Age = 36, Race = CharacterType.Human };

        var jsonString = JsonConvert.SerializeObject(mainPlayer);

生成的 Json 字符串是:

        {      "Name": "Dustin",      "Age": 36,      "Race": 20 } 

請注意上面的"Race"屬性的值统抬。 枚舉實際上是后面的整數(shù)火本。 枚舉本身是一個在整數(shù)值之上拋出的語法糖,以賦予它意義。 當序列化程序序列化枚舉值時,它會使用其整數(shù)值進行序列化聪建。 改用字符串值是可能的,而且非常常見钙畔。 我們在Serialization and Deserialization using Converters部分中介紹這一點。
您還可以控制生成的 json 的格式金麸。 有兩個選項可用:縮進和無擎析。 使用縮進選項可產生易于讀懂且非常適合調試的 json。

        var jsonString = JsonConvert.SerializeObject(mainPlayer, Formatting.None); 

反序列化與序列化非常相似,其區(qū)別在于反序列化Object是我們提供類型的泛型方法挥下。 還有一些非泛型重載,允許您指定類型參數(shù)和其他設置揍魂。 我們將在高級部分介紹其他設置。
假設我們擁有我們之前序列化的結果 Json棚瘟。

        {      "Name": "Dustin",      "Age": 36,      "Race": 20 } 

現(xiàn)在,我們要將它反序列化回對象现斋。 最簡單、最常見的方法是使用泛型反序列化方法偎蘸。

        var newPlayer = JsonConvert.DeserializeObject<PlayerInfo>(jsonString); 

這將給我們一個新的 PlayerInfo 實例,其中使用使用 json 字符串中的數(shù)據(jù)填充的Name庄蹋、Age和Race屬性瞬内。 當我們調用反序列化對象時,Json .Net 為我們創(chuàng)建了一個 PlayerInfo 的新實例,并從 json 中設置屬性。 默認情況下,如果 json 中有額外的屬性,則這些屬性將被忽略,如果 PlayerInfo 上有不在 json 字符串中的屬性,則這些屬性將僅設置為其默認值(或者您初始化它們的任何屬性)限书。
有時,您可能希望將 json 反序列化到現(xiàn)有對象上,而不是創(chuàng)建新的對象虫蝶。 這在某些對象池方案中很常見,或者在場景中已有對象并且只想加載一些數(shù)據(jù)并設置其屬性的情況下,這種情況很常見。 這是使用填充對象方法完成的倦西。 例如,假設我們創(chuàng)建了以下 PlayerInfo 類:

            var newPlayer = new PlayerInfo
            {
                Name = "Frank",
                Age = 54,
                Race = CharacterType.Orc
            };

現(xiàn)在,我們要用我們之前序列化的版本替換它能真。 我們可以使用以下代碼執(zhí)行此操作:

        JsonConvert.PopulateObject(jsonString, newPlayer); 

現(xiàn)在,我們的新Player對象將具有json字符串中的屬性,而不是我們指定的原始屬性。

Serialization and Deserialization using Converters

有時,您可能希望通過提供自定義 JsonConverter 來執(zhí)行序列化和反序列化,以便使用,而不是將它們添加到全局設置中调限。 例如,我們希望序列化和反序列化分辨率對象舟陆。 我們可以創(chuàng)建和維護 JsonConverters 數(shù)組,并將它們傳遞給序列化對象和反序列化對象調用,如下所示:

        var res = new Resolution {     height = 500,     width = 400 }; 
        var converter = new ResolutionConverter(); 
        var jsonString = JsonConvert.SerializeObject(res, converter); 
        var res2 = JsonConvert.DeserializeObject<Resolution>(jsonString, converter); 

對于此重載(和其他接受轉換器),提供的參數(shù)是 JsonConverter 類型的參數(shù)數(shù)組。 這意味著您可以傳遞單個轉換器或包含要應用的多個轉換器實例的 JsonConverter 數(shù)組耻矮。
需要注意的一點是,通過使用此方法,將只使用您提供的轉換器秦躯。 這意味著將不啟用默認轉換器(如哈希設置轉換器和矢量轉換器)。 為了使用這些,你會想包括他們的轉換器數(shù)組裆装。
另一種方法是構建Json序列程序設置的新實例,而不是包括默認轉換器踱承。 然后,您可以簡單地添加您的分辨率轉換器到轉換器集合。 下面是上面的示例,但改為使用 Json 序列程序設置實例:

        var res = new Resolution {     height = 500,     width = 400 }; 
        var settings = new JsonSerializerSettings(); 
        settings.Converters.Add(new ResolutionConverter());  
        var jsonString = JsonConvert.SerializeObject(res, settings); 
        var res2 = JsonConvert.DeserializeObject<Resolution>(jsonString, settings); 

Custom Object Creation with CustomCreationConverter

有時,我們可能需要手動處理對象的創(chuàng)建方式哨免。 如果有時需要對對象使用備用構造函數(shù)或返回繼承基的不同類類型,則此功能非常有用茎活。 自定義創(chuàng)建轉換器<T>是一個抽象類,可以繼承以創(chuàng)建您自己的轉換器。 它繼承了Json轉換器,所以可以像上面任何標準Json轉換器一樣使用琢唾。 要實現(xiàn)自定義創(chuàng)建轉換器,只需重寫返回類型 T 的 Create 方法载荔。
下面是具有兩個構造函數(shù)的類的示例。 第一個是默認的無參數(shù)構造函數(shù),第二個是采用 Vector3 位置的構造函數(shù):

        public class SpawnedItem
        {
            public Vector3 SpawnLocation { get; set; }
            public SpawnedItem() { SpawnLocation = Vector3.zero; }
            public SpawnedItem(Vector3 location) { SpawnLocation = location; }
        }

給定上面的示例,讓我們假設在某些情況下,我們希望使用第二個構造函數(shù),并將"location"默認為 vector3 x:0采桃、y:10懒熙、z:0。 以下自定義創(chuàng)建轉換器將允許我們這樣做:

        public class SpawnedItemCreationConverter : CustomCreationConverter<SpawnedItem>
        {
            public override SpawnedItem Create(Type objectType)
            {
                return new SpawnedItem(new Vector3(0, 10, 0));
            }
        }

要使用此創(chuàng)建轉換器,我們只需將其添加到轉換器集合中,就像使用任何標準 JsonConverter 一樣普办。 也可以通過屬性使用,我們將在"使用 Json 屬性"部分中演示這些屬性工扎。 需要注意的另一個重要事項是,提供給自定義創(chuàng)建轉換器的類型不必與要創(chuàng)建的項目的確切類型無關。 實際上,創(chuàng)建的項可以是 T 中指定的類型的子類型或實現(xiàn)衔蹲。
例如,假設 SpawnedItem 實現(xiàn)了一個稱為 ISpawn 的接口肢娘。 您可以將轉換器指定為繼承自定義創(chuàng)建轉換器<ISpawnable>并使用它默認創(chuàng)建實現(xiàn)該接口的任何類型。 如果您已使用 JsonSerializerSettings 指定 TypeNameHandling.Auto舆驶、Object 或 All,則預期的實際具體類型將作為對象Type 參數(shù)傳入,從而允許您分別處理不同對象的創(chuàng)建橱健。
另一個常見的例子就是某種工廠。 根據(jù) objectType 參數(shù)中提供的類型,您可能希望與對象池解決方案集成,以便從池中檢索對象,而不是直接向上" new"贞远。

Customizing Serialization Settings

默認序列化設置可以修改,如"修改默認序列化設置"部分所述,但您也可以創(chuàng)建并提供您自己的自定義序列化設置畴博。 這使您可以使用 Json 序列化器設置的新實例靈活地為不同的序列化和反序列化方案提供不同的設置。 在 Unity 的上下文中,建議您為所需的每個方案創(chuàng)建一個實例并緩存它,以避免向堆添加分配蓝仲。

Providing Custom Serialization Settings

您可以通過修改默認設置或向序列化程序提供 Json 序列化程序設置的新實例來自定義序列化器的工作方式。 以下是 Json 序列化程序設置上可用的常見屬性。 此處未提及的概念是更高級的概念,您可以在正式的 Json .Net 文檔中了解有關它們的更多內容袱结。
ObjectCreationHandling –控制如何創(chuàng)建對象亮隙。 默認值為"Auto",它將創(chuàng)建新對象或更新現(xiàn)有對象。 如果類默認初始化成員,Json .Net 將填充該現(xiàn)有對象的屬性,而不是將其替換為新實例(如果設置為"Auto")垢夹。 將其設置為"Replace "將導致對象始終被新實例替換,并將對象設置為" Reuse "將意味著僅填充現(xiàn)有實例,并且永遠不會創(chuàng)建新實例溢吻。 在大多數(shù)情況下,這應留為"Auto"的默認值。
CheckAdditionalContent –默認情況下,如果 Json .Net 到達對象末尾后在 json 字符串中遇到額外的 json(注釋除外),則 Json .Net 將引發(fā)異常果元。 如果希望序列化程序忽略在 json 字符串末尾找到的額外內容,請將此屬性設置為 false促王。
ConstructorHandling –Json .Net 希望對象具有默認的公共無參數(shù)構造函數(shù)。 如果需要使用非標準構造函數(shù),可以使用自定義創(chuàng)建轉換器覆蓋特定對象的此行為,但也可以告訴 Json .Net 查找私有無參數(shù)構造函數(shù)而晒。 默認情況下,構造函數(shù)操作設置為"Auto"蝇狼。 您可以將此設置更改為允許此功能的非公共默認構造函數(shù)。
Converters –轉換器屬性包含 JsonConverter 對象的集合倡怎。 這些轉換器負責提供某些對象類型的自定義序列化和反序列化迅耘。 每當創(chuàng)建 JsonSerializer 設置的新實例時,它將預先填充默認轉換器類型,此時您可以添加其他轉換器和/或刪除默認值。 custom creation converter部分介紹如何創(chuàng)建自己的轉換器监署。
Culture –定義讀取 Json 時使用的本地化區(qū)域性颤专。 默認情況下,此設置為"CultureInfo.InvariantCulture"。 如果您需要閱讀國際化的 Json,您可能需要修改此內容钠乏。 在大多數(shù)情況下,不需要更改默認值栖秕。
DateFormatHandling –此設置定義如何序列化和寫入日期。 默認情況下,使用 IsoDateFormat 設置編寫日期,該設置以 Iso 格式序列化日期晓避。 如有必要,您可以將此更改為 MicrosoftDate 以使用 Microsoft 日期格式,盡管在幾乎所有情況下,IsoDateFormat 都是最合適的
DateFormatString –此屬性允許您使用格式字符串自定義用于日期簇捍、時間和時區(qū)偏移的格式。 但是,請注意,序列化器在讀取日期和時間時也會期望日期采用此格式够滑。 有關有效的格式字符串,請參閱 .NET 3.5 文檔垦写。
DateTimeZoneHandling –此設置指定在反序列化日期時如何處理日期。 .NET 中的日期時間對象可以具有日期時間類型的并保存時區(qū)信息彰触。 默認情況下,對新 DateTime() 的調用將創(chuàng)建一個"類型"設置為"Unspecified"的日期時間對象梯投。 DateTimeZoneHandling 設置允許您控制 Json .Net 如何處理來自 json 數(shù)據(jù)的創(chuàng)建和轉換。 本地表示如果日期時間字符串已格式化為 UTC,則它們將轉換為本地日期時間况毅。DateTimeZoneHandling 意味著在序列化或反序列化時保留時間和時區(qū)信息分蓖。 未指定表示將使用默認的 .NET DateTime 創(chuàng)建處理。 Utc 表示該值將轉換為 Utc 時間,并將 Utc 指定為日期時間尔许。
DefaultValueHandling –默認情況下,對象上的所有公共字段和屬性都寫入生成的 json,即使它們?yōu)榭?或默認值(int 的默認值,如 0)么鹤。 如果屬性存在于類上,但不在 json 字符串中,則忽略這些屬性。 此設置修改此行為如下:Ignore表示設置為其默認值的屬性(對象為 null,布爾為 false,int 為 0 表示),等等)不包括在輸出 json 中味廊。 對于僅需要值(如果它們?yōu)榉悄J值)的情況,這可能會導致更緊湊的 json蒸甜。include是默認設置,將成員寫入生成的 json,即使它們具有默認值也是如此棠耕。 IgnoreAndPopulate執(zhí)行與序列化時的Ignore相同,但在反序列化時將屬性設置為其默認值時,它們從 Json 中丟失。 Populate句柄序列化的方式與Include相同,但如果 json 字符串中缺少成員,則會將其設置為對象上的默認值柠新。
Error –這是一個事件處理程序,允許您指定在序列化或反序列化出錯時執(zhí)行的處理程序窍荧。
Formatting –指定生成的 Json 字符串的格式設置方式。 縮進提供了易于閱讀和調試的prettyjson恨憎。 "None’"創(chuàng)建沒有indents / spacing的緊湊 json蕊退。
MissingMemberHandling –默認情況下,此屬性設置為Ignore,這意味著如果 Json 的屬性在目標對象上不存在,則只會被忽略。 如果 json 包含的目標對象類型上不存在的成員,則將此設置為"錯誤"將導致引發(fā)異常憔恳。
NullValueHandling –選項為IncludeIgnore瓤荔。 此選項指定在序列化和反序列化數(shù)據(jù)時是否應包括 null 值。 默認值為Include钥组。
PreserveReferencesHandling –默認情況下,此值設置為None输硝。 其他選項是All,ArraysObjects。 此設置指示序列化程序在序列化時記住引用者铜。 生成的 Json 將包括標識對象的$ref屬性腔丧。 這些對象將僅反序列化一次,并且將還原對象之間的引用。
ReferenceLoopHandling –有時,序列化程序會遇到循環(huán)或循環(huán)引用作烟。 參考LoopHandling 指示序列化器在自定義轉換器可能尚未處理的情況下應該怎么做愉粤。 選項為"錯誤"、"忽略"和"序列化"拿撩。 檢測到錯誤引發(fā)帶有引用循環(huán)的異常衣厘。 忽略將忽略引用循環(huán),而不是序列化屬性。 序列化將序列化循環(huán)压恒。 如果循環(huán)永遠不會結束,將引發(fā)錯誤影暴。 默認設置為"錯誤"。
TypeNameHandling – 指定類型名稱是否通過"type"屬性包含在生成的 json 中探赫。 對于接口定義為目標類型的多態(tài)序列化和反序列化對象,這是必要的型宙。 默認值為"無",其中不包含類型信息。 所有內容都包含所有類型信息伦吠。 序列化數(shù)組時,數(shù)組包含類型信息妆兑。 序列化對象時,對象包括類型信息。 當正在序列化的類型與聲明的類型不同時,Auto 指定類型信息(例如,是繼承屬性類型的類,如果是接口,則實現(xiàn)它)毛仪。

Using Json Attributes

JsonConverter Attribute

JsonConverter 屬性是一個更常用的屬性搁嗓。 可以使用此屬性指定定義類或屬性時要使用的轉換器。 例如,如果我們有一個具有 Uri 屬性的類,并且我們希望使用包含的 UriConverter,則可以使用 JsonConverter 屬性將其指定如下:

        using Newtonsoft.Json.Converters; 
        public class GamerProfile 
        {     
              public string GamerTag { get; set; } 
              [JsonConverter(typeof(UriConverter))]     
              public Uri ProfileLink { get; set; } 
        }

這告訴序列化器和去序程序在此類序列化或反序列化時,使用 UriConverter 屬性的 ProfileLink 屬性箱靴。 具有 Uri 屬性的 Uri 或類的任何其他實例不會使用此轉換器,除非它還被傳遞到序列化器或包含在JsonSerializerSettings.

JsonProperty Attribute

JsonProperty 屬性為我們提供了對特定屬性的序列化和反序列化方式的更精細的細粒度控制腺逛。 JsonProperty 最常見的兩個用途是指定要在 json 字符串中使用的不同名稱,或者是否需要使用私有屬性 getter 或 setter。 當包含 JsonProperty 屬性時,序列化程序不僅將序列化公共屬性,而且還將使用內部和私有 getter 和 setter衡怀。
例如,假設我們有一個具有名為 Name 的屬性的 Player 類,但我們從以 player_name 發(fā)送回的 Web 服務獲取 json 字符串棍矛。 json 如下所示:

        {  "player_name": "Lucius",  "rank": 23456 } 

我們可以使用 JsonProperty 屬性將玩家類的名稱屬性"映射"到"玩家名稱"名字對象安疗。 這將將 Json 字符串中的"播放器名稱"值歸為"Name"屬性,當對播放機類進行序列化時,它將將 Name 屬性序列化回"player_name"。
我們的Player類如下所示:

       public class Player
       {
          [JsonProperty("player_name")]
          public string Name { get; set; }
          public int Rank { get; set; }
        }

此外,JsonProperty 還可用于設置各種其他選項,甚至用于覆蓋序列化器設置(如 TypeNameHandling 和 DefaultValueHandling)上的選項茄靠。 JsonProperty 屬性的完整引用可在此處找到 茂契。

JsonIgnore Attribute

JsonIgnore 屬性可用于忽略屬性蝶桶。 在下面的示例中,"Foo"屬性被完全忽略,但"Bar"屬性是序列化的慨绳。

        public class Demo
        {
              [JsonIgnore] public string Foo { get; set; }
              private string Bar { get; set; }
        }

Additional Attributes

還有更多的屬性。 由于它們不是常用的,隨著時間的推移,它們將添加到本文檔中真竖。 現(xiàn)在,您可以在此處查看所有屬性和類型的引用脐雪。

Advanced Serialization and Deserialization

Json Without a Matching Class

有時,您可能希望使用原始 json 而不具有與您的 json 結構相匹配的類。 這可以通過使用 JObject 類來實現(xiàn),該類將數(shù)據(jù)反序列化為鍵/值集合恢共。 對于 json 數(shù)組,您可以使用 JArray 類執(zhí)行相同的操作战秋。
JObject 和 JArray 類位于牛頓軟.Json.Linq 命名空間中。 您可以使用這些對象來序列化和反序列化 json讨韭。 使用 JObject 創(chuàng)建快速 json 字符串的一個簡單示例如下所示:

        var jo = new JObject();
        jo.Add("PlayerName", "Frank"); jo.Add("Age", 36);
        var json = jo.ToString();

此方法適用于基元值,如 int脂信、bool 和字符串,因為它們和 JToken 之間存在隱式轉換器。 JObject 繼承 JToken,因此您始終可以將 JObject 作為屬性添加到另一個 JObject,或者可以使用 JToken 的 FromObject 方法透硝。 例如,如果您有一個稱為 PlayerStats 的類,并且想要將其添加到上述示例中,則如下所示:

        var jo = new JObject();
        jo.Add("PlayerName", "Frank");
        jo.Add("Age", 36);
        jo.Add("Stats", JToken.FromObject(stats));
        var json = jo.ToString();

還可以從 json 字符串創(chuàng)建新的 JObject狰闪。 對于此示例,我們將假定我們有以下 json 字符串,該字符串表示一個復雜對象并包含一個數(shù)組。

        {
            "PlayerId": 5345,
            "Name": "L33tN00b",
            "Likes": [
            {
              "Type": "Mammal",
              "Name": "Kitten"
            },
            {
              "Type": "Bird",
              "Name": "Eagle"
            }
          ]
      }

對于此示例,完全理解上面的 json 并不重要,但如果您想知道到底發(fā)生了什么,您可以跳到 Appendix B: JSON Structure Primer濒生。 現(xiàn)在只需知道它代表一個對象與 PlayerId, 名稱和喜歡屬性. "贊"屬性是具有"類型"和"Name"屬性的對象數(shù)組埋泵。 要分析此 json 字符串,只需使用 JObject.Parse:

        var jo = JObject.Parse(jsonString); 

使用我們在上面創(chuàng)建的 JObject,我們可以按鍵名稱獲取所需的屬性,因為 JObject 還充當字典字符串 JToken。 由于每個值都是 JToken,因此可以通過多種方法恢復該數(shù)據(jù)罪治。 JTokens 具有一個 Value<T> 方法,它允許您返回具有隱式轉換的類型,以及一個 ToObject<T> 方法,它允許您將其反序列化為具體對象丽声。 您還可以使用 ToString(),它將為該特定 JToken 返回 json,或者,如果它是一個復雜的對象,則可以枚舉其屬性或直接訪問其鍵。
給定上述語句,假設我們想要訪問第二個"喜歡"對象,并找出其名稱是什么觉义。 可以按照以下方式完成:

        var likeName = jo["Likes"][1]["Name"].Value<string>(); 

有時,您可能需要將整個屬性反序列化回一個具體類雁社。 在這種情況下。值<T>不會剪切它,因為 JToken 和您的類型之間沒有隱式轉換晒骇。 在這種情況下,您需要使用 ToObject<T> 方法,該方法將 JToken 反序列化為具體類霉撵。 例如,如果具有名為 LikeItem 的類,該類具有 Type 屬性和 Name 屬性(兩者都是類型字符串),則可以根據(jù)以下示例將其反序列化:

        var likeObj = jo["Likes"][1].ToObject<LikeItem>(); 

Serializing With Interfaces or Base / Inherited Classes

有時,需要執(zhí)行序列化和反序列化,這涉及多態(tài)化(將繼承的類視為基類),或者序列化和反序列化其屬性并由接口定義的對象。 讓我們舉下下面的示例厉碟。 在這里,我們有一個可擊功能接口和一個武器基地類喊巍。 我們也有一個步槍類,繼承武器基地和實現(xiàn)IShootable:

        public interface IShootable
        {
            int Ammunition { get; set; }
            void Fire();
        }
        public abstract class WeaponBase
        {
            public abstract void Equip();
        }

        public class Rifle : WeaponBase, IShootable
        {
            public int Ammunition { get; set; } //IShootable.Ammunition 

            public override void Equip() //WeaponBase.Equip     
            {
            //Equip the weapon     
            }
            public void Fire() //IShootable.Fire     
            {
            //Fire the weapon     
            }
        }

現(xiàn)在,我們可以引用此類型的三種主要方法。 下面的類有三個"武器"插槽,每個插槽引用它不同:
···
public class WeaponDemo
{
public WeaponBase Weapon1 { get; set; }
public IShootable Weapon2 { get; set; }
public Rifle Weapon3 { get; set; }
}
···
在上面的示例中,步槍類的實例可以分配給武器1,武器2和武器3,因為步槍既繼承武器基地,并實施I可射擊箍鼓。 武器模擬類的實例將序列化精細,但是,我們將不能反序列化它崭参。
這是因為反序列化程序不會通過查看 json 來知道具體類型是什么。 要反序列化的對象說,它應該是武器基礎和ISable,但是你不能創(chuàng)建一個抽象類或接口的新實例款咖。 那么,我們如何解決這個問題呢何暮?
Json .NET 能夠將類型信息與 json 一起存儲奄喂。 如果您還記得 Customizing Serialization Settings部分,我們可以看到 Json 序列化器設置對象的 TypeNameHandling 屬性。 在這種情況下,將其設置為"自動"是最適合的,因為它會在名為 type的 json 中創(chuàng)建一個額外的變量,該變量將存儲具體類型信息海洼。 它只會這樣做的武器1和武器2時,使用自動,因為武器3已經是步槍類型,所以沒有必要存儲的類型跨新。
重要提示:在序列化和反序列化時,您需要使用這些設置,以便它知道在重新創(chuàng)建對象時存儲$type值并讀取它們。

Creating a Custom JsonConverter

通過編寫自定義轉換器,可以完全自定義對象序列化和反序列化的方式坏逢。 這些是繼承 Json 轉換器的特殊類域帐。 我們已經討論過內置的轉換器是這些示例,例如矢量轉換器、哈希集轉換器和顏色轉換器是整。
Json 轉換器可能很復雜肖揣。 在以后的更新中,我們將包含更多有關創(chuàng)建 Json 轉換器的文檔和示例。 現(xiàn)在,您可以通過查看 JsonConverter 的官方示例和 API 文檔來了解更多信息浮入。

Binary Serialization with BSON

雖然序列化到 json 格式的數(shù)據(jù)對于簡單易用性非常方便,但有時您可能想要以二進制格式序列化的內容龙优。 這使得保存數(shù)據(jù)等內容更難篡改,因為它們不是以純文本格式存儲的。 它還使最終有效負載更小,并且與二進制的序列化和反序列化比 json 更快事秀。
Json .NET 支持一種稱為"BSON"的格式,它是二進制 json 表示法彤断。 序列化和反序列化與bson是有點不同。 您需要使用 BsonWriter 將序列化數(shù)據(jù)寫入流(或從流讀取的讀取器)易迹。 該流可以是文件流宰衙、內存流、網(wǎng)絡請求流等赴蝇。
下面的示例在持久數(shù)據(jù)路徑中創(chuàng)建一個名為 PlayerInfo.dat 的文件菩浙。 它序列化 PlayerInfo 的實例并將其寫入文件:

        var pi = new PlayerInfo
        {
            Name = "Nemo",
            SkillLevel = 60,
            Health = 74
        };
        var filePath = Path.Combine(Application.persistentDataPath, "PlayerInfo.dat");
        using (var fs = File.Open(filePath, FileMode.Create))
        {
            using (var writer = new BsonWriter(fs))
            {
                var serializer = new JsonSerializer();
                serializer.Serialize(writer, pi);
            }
        }

在這里,用于 Json 序列化的同一個序列化器,但是,我們不是將數(shù)據(jù)寫入帶有 JsonWriter 的 json Writer 字符串,而是將 BsonWriter 傳遞給具有對流的引用的序列化器(在本例中為 FileStream)。 BsonWriter 將二進制結果寫入流句伶。
要對文件的內容進行反序列化,我們只是反轉過程劲蜻。 在這里,我們使用 BsonReader 讀取 FileStream 的內容,然后將其反序列化回 PlayerInfo 實例:

        PlayerInfo pi;
        using (var fs = File.OpenRead(filePath))
        {
            using (var reader = new BsonReader(fs))
            {
                var serializer = new JsonSerializer();
                pi = serializer.Deserialize<PlayerInfo>(reader);
            }
        }

當數(shù)據(jù)表示集合(例如數(shù)組或列表)時,bson 的讀取會稍有變化。 BsonReader 希望將第一個二進制字符讀取為對象,因此,如果您以前序列化了 List<PlayerInfo> 或數(shù)組 (PlayerInfo_),則需要在反序列化時告訴讀取器它是數(shù)組考余。
要告訴 BsonReader 您正在使用數(shù)組,您需要設置構造讀取器的 ReadRootValueAsArray 屬性先嬉。 下面的示例演示如何對播放機Info.dat 文件進行反序列化,如果該文件包含 PlayerInfo 對象的集合:

        List<PlayerInfo> players;
        using (var fs = File.OpenRead(filePath))
        {
            using (var reader = new BsonReader(fs))
            {
                reader.ReadRootValueAsArray = true;
                var serializer = new JsonSerializer();
                players = serializer.Deserialize<List<PlayerInfo>>(reader);
            }
        }

Appendix A: Platform DLL Mapping

下表顯示了哪些平臺映射到每個 DLL。 隨著時間的推移,Unity 還會添加未預映射的其他平臺楚堤。 在幾乎所有情況下,這些平臺都應映射到 /組件/AOT/牛頓軟.Json.dll疫蔓。 如果有疑問或平臺不適合您,請給我們發(fā)送電子郵件:dustin@parentelement.com
如果您不熟悉程序集映射,這是在 Unity 5 中添加的功能身冬。 要將程序集映射到特定平臺,請在項目資源管理器中選擇 DLL衅胀。 在該文件的檢查器中,您可以指定要使用的平臺和腳本后端。 程序集映射過程存在一些限制酥筝。 例如,如果不指定"任意 SDK"選項,就無法將相同的 DLL 映射到 Windows SDK8.1 和 UWP滚躯。 這意味著我可以指定另一個僅與 SDK 8.0(或 Windows Phone 8)一起工作的 DLL。
EditorStandalone: /JsonDotNet/Assemblies/Standalone/Newtonsoft.Json.dll
iOS掸掏、Android茁影、WebGLWSAPlayer (IL2CPP Backend)丧凤、Tizen募闲、SamsungTVtvOS (AppleTV)愿待、Xbox360 *浩螺、 XboxOne *WiiU *呼盆、PS3 * 年扩、PS4 *:/JsonDotNet/Assemblies/AOT/Newtonsoft.Json.dll
WSAPlayer (.NET Backend) **:/JsonDotNet/Assemblies/Windows/Newtonsoft.Json.dll ***
** Note: 控制臺當前未映射,因為我無法訪問 SDK。 我可以依靠其他人來測試我,但是,在提交到資產存儲之前,我無法映射最終包访圃。 因此,如果您在控制臺上進行開發(fā),則需要使用上面的指南自行映射 DLL。
** Note: WSAPlayer DLL 是針對 .NET 4.5 構建的相嵌。 因此,Windows 的映射還為您提供了選擇將在編輯器中使用的占位符 DLL 的選項腿时。 請使用 /JsonDotNet/組件/獨立/牛頓軟.Json.dll 作為 WSAPlayer 映射的占位符。
** Note:即使映射了占位符,Unity 編輯器仍嘗試讀取 DLL 以在首次加載包時檢查腳本升級饭宾。 如果不在 Windows 10 上進行開發(fā),您可能會在編輯器中看到一個錯誤,指示它無法讀取 DLL批糟。 您可以暫時安全地忽略此錯誤。 我將報告它作為一個錯誤,所以Unity可以修復這一點在未來的版本看铆。

Appendix B: JSON Structure Primer

Json 是一個簡單的數(shù)據(jù)結構徽鼎。 屬性名稱由引號括起來。 屬性名稱和值用冒號分隔弹惦。 字符串值用引號括起來否淤。 數(shù)值未引號。 對象被大括號包圍棠隐。 數(shù)組由方括號包圍石抡。 逗號分別屬性和數(shù)組元素。
下面是一些基本示例:

        // 序列化為 json 的簡單字符串助泽。
        "Lorum Ipsum" 
      // 具有Name和Age屬性的對象啰扛。 Name是一個字符串,Age是一個數(shù)字嗡贺。
      {
        "Name": "Dustin",
        "Age": 36
      } 
        // 數(shù)字數(shù)組
        [2, 11, 85, 79, 41] 
        // 具有 Name 屬性和LuckyNumbers屬性的對象隐解。 Name 是字符串,LuckyNumbers是數(shù)字數(shù)組。
        {
          "Name": "Dustin",
          "LuckyNumbers": [ 2, 11, 85, 79, 41 ]
        } 
         // 與上一個對象一樣,但在這種情況下,"技能"是一個對象數(shù)組诫睬。
        {
          "Name": "Dustin",
          "Skills": [
            {
              "Id": 1,
              "Level": 30
            },
            {
              "Id": 12,
              "Level": 8
            }
          ]
        } 
        // 具有Name和Attributes屬性的對象煞茫。 在這種情況下,屬性也是一個對象,它將由單獨的類表示。 由于屬性的所有三個屬性都是整數(shù),因此屬性也可以為類型Dictionary<string,int>。
        {
            "Name": "Dustin",
            "Attributes": {
            "Age": 36,
            "HeightInches": 69,
            "WeightPounds": 189
          }
      }

Developer Support Contact

Developer:
Dustin Horne
Email: dustin@parentelement.com
Twitter: @dustinhorne Company
Website: http://www.parentelement.com

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末溜嗜,一起剝皮案震驚了整個濱河市宵膨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌炸宵,老刑警劉巖辟躏,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異土全,居然都是意外死亡捎琐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門裹匙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瑞凑,“玉大人,你說我怎么就攤上這事概页∽延” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵惰匙,是天一觀的道長技掏。 經常有香客問我,道長项鬼,這世上最難降的妖魔是什么哑梳? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮绘盟,結果婚禮上鸠真,老公的妹妹穿的比我還像新娘。我一直安慰自己龄毡,他們只是感情好吠卷,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著稚虎,像睡著了一般撤嫩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蠢终,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天序攘,我揣著相機與錄音,去河邊找鬼寻拂。 笑死程奠,一個胖子當著我的面吹牛,可吹牛的內容都是我干的祭钉。 我是一名探鬼主播瞄沙,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了距境?” 一聲冷哼從身側響起申尼,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎垫桂,沒想到半個月后师幕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡诬滩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年霹粥,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疼鸟。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡后控,死狀恐怖,靈堂內的尸體忽然破棺而出空镜,到底是詐尸還是另有隱情滥搭,我是刑警寧澤耻瑟,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布拷肌,位于F島的核電站黔攒,受9級特大地震影響,放射性物質發(fā)生泄漏舶斧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一察皇、第九天 我趴在偏房一處隱蔽的房頂上張望茴厉。 院中可真熱鬧,春花似錦什荣、人聲如沸矾缓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嗜闻。三九已至,卻和暖如春桅锄,著一層夾襖步出監(jiān)牢的瞬間琉雳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工友瘤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翠肘,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓辫秧,卻偏偏與公主長得像束倍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內容