jsonb 為什么會影響 System.Text.Json
我在將一個屬性映射到 jsonb 類型時遇到這樣一個問題 —— 我有一個抽象基類 BaseClass 和一個派生類 DerivedClass:
[JsonDerivedType(typeof(DerivedClass), typeDiscriminator: "derived")] public class BaseClass { public BaseClass() { } } public class DerivedClass : BaseClass { .... }
當(dāng)持久化數(shù)據(jù)后,我可能得到這樣的數(shù)據(jù):
{ "$type": "derived", ... }
或
{ "value": 131121, "$type": "derived", ... }
第一個 json 中,類型鑒別器($type)是 json 里的第一個屬性;而第二個 json 字符串則不是這種情況。當(dāng)我執(zhí)行 Deserialize 方法時,第二個 json 字符串會拋出異常。
System.Text.Json.JsonException : The metadata property is either not supported by the type or is not the first property in the deserialized JSON object. Path: $.$type | LineNumber: 0 | BytePositionInLine: 47.
問題原因
System.Text.Json 的多態(tài)反序列化限制
當(dāng)使用 [JsonDerivedType] 時,System.Text.Json 要求類型鑒別器(如 $type)必須是 json 中的第一個屬性。如果鑒別器不在首位,反序列化會失敗并拋出異常。
PostgreSQL 的存儲特性
- json:以原始文本形式存儲,完全保留輸入的 json 字符串格式(包括空格、重復(fù)鍵、順序等)。
- jsonb:以二進(jìn)制形式存儲,會對 json 進(jìn)行解析和規(guī)范化(例如去重鍵、忽略多余空格、重新排序鍵)。
jsonb 類型會自動對 json 屬性進(jìn)行排序,導(dǎo)致存儲后的屬性順序與序列化時不同。例如:{"$type":"derived","value": xxx } 存儲到 jsonb 后可能變?yōu)椋簕"value": xxx ,"$type":"derived"} 這種順序變化會引發(fā) System.Text.Json 的異常。
解決方案
其實微軟在官方文檔中已經(jīng)給出了說明:

通過設(shè)置 AllowOutOfOrderMetadataProperties 屬性為 true,可解決此問題:
JsonSerializerOptions options = new() { AllowOutOfOrderMetadataProperties = true };
如果您沒有找到該屬性,請升級到高版本。

作者:MeteorSeed
我希望您喜歡這篇博文,并一如既往地感謝您閱讀并與朋友和同事分享我的博文。
轉(zhuǎn)載請注明出處。

浙公網(wǎng)安備 33010602011771號