c# - 是否可以序列化 System.Text.Json 中列表成员的派生属性?
问题描述
根据以下文件System.Text.Json
:
要序列化派生类型的属性,请使用以下方法之一:
- (...)
- 将要序列化的对象声明为
object
.
不幸的是,正如我刚刚发现的那样,这不允许序列化列表成员的派生属性。考虑以下 DTO 类:
public abstract class GameUpdate
{
public abstract string Type { get; }
}
public class ConsoleMessage : GameUpdate
{
public override string Type => "ConsoleMessage";
public string MessageContent { get; set; }
}
public class HitpointsUpdate : GameUpdate
{
public override string Type => "HitpointsUpdate";
public long MonsterID { get; set; }
public long NewHP { get; set; }
}
它们应该用作List<GameUpdate>
. 不幸的是,将要序列化的列表声明为object
仍然无法序列化重要属性:
var gameUpdates = new List<GameUpdate>
{
new ConsoleMessage { MessageContent = "Chimzee lost 10 HP!"},
new HitpointsUpdate { MonsterID = 5, NewHP = 90 }
};
var json = System.Text.Json.JsonSerializer.Serialize<object>(gameUpdates);
Console.WriteLine(json);
这会产生以下 JSON:
[{"Type":"ConsoleMessage"},{"Type":"HitpointsUpdate"}]
为了比较, usingNewtonsoft.Json.JsonConvert.SerializeObject(gameUpdates)
产生以下结果:
[{"Type":"ConsoleMessage","MessageContent":"Chimzee lost 10 HP!"},{"Type":"HitpointsUpdate","MonsterID":5,"NewHP":90}]
是否可以使用 获得类似的结果System.Text.Json
?
为什么我要问这个:我一直在尝试开发基于浏览器的游戏作为一个爱好项目,而这正是我实现服务器与浏览器通信的方式。随着 Asp .NET Core 3 的出现,它的文档鼓励从 Newtonsoft.JSON 迁移到 System.Text.Json。在阅读了可以进行多态序列化的文档后,我删除了与 Newtonsoft 相关的代码并开始使用 System.Text.Json,却发现游戏不再工作。
解决方案
这有效:
var gameUpdates = new List<object>
{
new ConsoleMessage { MessageContent = "Chimzee lost 10 HP!"},
new HitpointsUpdate { MonsterID = 5, NewHP = 90 }
};
var json = JsonSerializer.Serialize(gameUpdates);
Console.WriteLine(json);
[{"Type":"ConsoleMessage","MessageContent":"Chimzee lost 10 HP!"},{"Type":"HitpointsUpdate","MonsterID":5,"NewHP":90}]
旁注:您的方法可能很危险,您必须保留允许类型的白名单以再次反序列化,否则攻击者可以注入他自己的类型的创建......在一个集合中序列化一种类型的对象要安全得多.
如果攻击者注入这样的代码怎么办:
“类型”:“System.Drawing.Bitmap”,“宽度”:“100000”,“高度”:“100000”
推荐阅读
- pointers - 当我想使用 llvm api 将数组 ref 传递给函数时该怎么办?
- r - R xaringan 构造页脚以自动包含标题/作者
- javascript - 有没有办法使用 HTML 和 CSS 在 SVG 路径上制作滚动选取框?
- python - 如何将模型最后一层的输出添加到我创建的附加数组中?
- javascript - 在 Firebase 错误上使用电话号码进行身份验证:“无法加载外部 reCAPTCHA 依赖项!”
- git - 如何恢复以前的文件和更改
- r - 如何从 R 中的一列字符串中查找并返回匹配值?
- r - 如何绘制具有两组的 CoxPH 模型?
- java - 在片段android studio中处理appbar中的clickevent
- outlook - 尽管获得了同意的权限,但 Microsoft Graph API 读取邮件状态代码 404 未找到错误