【发布时间】:2018-10-18 16:48:29
【问题描述】:
我正在使用System.Web.Script.Serialization.JavaScriptSerializer 序列化/反序列化扩展 Dictionary 的类。
问题是,我的自定义属性没有被序列化。这是我的课:
public class Test : Dictionary<string, object> {
public ushort Id { get; set; }
public string Name { get; set; }
}
还有我的代码:
var jss = new JavaScriptSerializer();
var test = new Test {
Id = 123,
Name = "test"
};
var json = jss.Serialize(test);
json 中的结果是一个空的 json {}
我不想依赖 Newtonsoft 或 JSON.Net 或任何其他库。
附加信息
我在同时使用dynamic 和object 时注意到一些,嗯,特殊性:
JavaScriptSerializer将任意数值默认为int。另外,
Newtonsoft将任意数字默认为long。
这可能会导致使用属性索引器的类中出现强制转换异常(如已接受的答案中所建议的那样),例如:
public class Test : Dictionary<string, dynamic> {
public ushort Id { get => this[nameof(Id)]; set => this[nameof(Id)] = value; }
}
Id 属性 getter 将尝试将 int 隐式转换为 ushort,这将失败。
附加信息 2
我刚刚发现 Newtonsoft 有很多奇怪的行为:
我添加了这些属性来解决“long to ushort”问题:
[JsonObject(MemberSerialization.OptIn)]
public class Test : Dictionary<string, dynamic> {
[JsonProperty]
public ushort Id { get => this[nameof(Id)]; set => this[nameof(Id)] = value; }
}
以上工作!但是当属性是引用类型时:
[JsonObject(MemberSerialization.OptIn)]
public class Test : Dictionary<string, dynamic> {
[JsonProperty]
public ushort Id { get => this[nameof(Id)]; set => this[nameof(Id)] = value; }
[JsonProperty]
public Test Child { get => this[nameof(Child)]; set => this[nameof(Child)] = value; }
}
它会在序列化之前尝试获取属性,从而导致“找不到键异常”。我不明白为什么它只在它是引用类型时才尝试获取该属性,这对我来说似乎是一个错误......
所以你必须这样做:
public Test Child { get => this.ContainsKey(index) ? this[nameof(Child)] : null; ... }
【问题讨论】:
-
您可能需要考虑使用组合而不是继承。 (改为使用字典属性)
-
没有重新实现大部分 JavaScriptObjectDeserializer (referencesource.microsoft.com/#system.web.extensions/Script/…),不确定是否可以。 MSDN 文档建议使用 JSON.NET 而不是这种方法。仅支持 [IgnoreJson](不支持 [JsonProperty] 或任何可用)
-
即使JavaScriptSerializer's API docs page 也建议只使用 JSON.Net。但是,查看文档,您可能需要实现自己的
JavaScriptConverter,因为似乎没有与ScriptIgnoreAttribute 相反。
标签: c# json.net javascriptserializer