使用JavaScriptSerializer反序列化时object转Dictionary的问题
解决JavaScriptSerializer反序列化object类型转为Dictionary的问题
问题原因
JavaScriptSerializer序列化object类型属性时,不会保留原始对象的类型信息。反序列化时,它无法识别原本的ChildClass类型,就会默认将JSON中的键值对转换成Dictionary<string, object>。
解决方案
方案1:改用Newtonsoft.Json(推荐)
Newtonsoft.Json支持保留类型信息,能自动识别并还原原始类型,步骤如下:
- 安装Newtonsoft.Json NuGet包
- 修改序列化和反序列化代码:
var obj = new ParentClass() { Name = "Charles", Item = new ChildClass() { Location = "Chicago" }, Dept = new Department() { DeptName = "IT" } }; // 序列化时保留类型信息 var json = JsonConvert.SerializeObject(obj, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }); // 反序列化时读取类型信息 var finalRes = JsonConvert.DeserializeObject<ParentClass>(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
这样反序列化后,Item属性会还原为ChildClass实例。
方案2:给JavaScriptSerializer自定义类型转换器
如果必须使用JavaScriptSerializer,可以通过自定义转换器来手动处理类型识别和还原:
- 创建自定义转换器类:
public class ChildClassConverter : JavaScriptConverter { public override IEnumerable<Type> SupportedTypes { get { return new List<Type> { typeof(ChildClass), typeof(object) }; } } public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) { var child = obj as ChildClass; if (child == null) return null; return new Dictionary<string, object> { { "$type", "ChildClass" }, // 添加类型标识 { "Location", child.Location } }; } public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { if (dictionary.TryGetValue("$type", out var typeObj) && typeObj.ToString() == "ChildClass") { return new ChildClass { Location = dictionary["Location"]?.ToString() }; } return null; } }
- 使用转换器进行序列化和反序列化:
var serializer = new JavaScriptSerializer(); serializer.RegisterConverters(new[] { new ChildClassConverter() }); var json = serializer.Serialize(obj); var finalRes = serializer.Deserialize<ParentClass>(json);
方案3:直接修改ParentClass的Item属性类型
如果Item属性只会存储ChildClass实例,最简单的办法是把Item的类型从object改成ChildClass:
public class ParentClass { public string Name { get; set; } public ChildClass Item { get; set; } = new ChildClass(); // 修改类型为ChildClass public Department Dept { get; set; } }
这样序列化和反序列化时,Item会始终保持ChildClass类型,无需额外处理。
内容的提问来源于stack exchange,提问作者Sravani Yadav
相关产品推荐
相关产品推荐

