使用JavaScriptSerializer进行JSON序列化时自定义JavaScriptConverter的问题

showlin 2012-06-26 05:14:19
有史以来第一次发这么长的题目,先汗一个~~~
要序列化的类如下

public class TestAAA
{
public string Name
{
get;
set;
}
public DateTime? BirthDay
{
get;
set;
}
}


TestAAA obj = new TestAAA
{
Name = "张三",
BirthDay = DateTime.Now
};
JavaScriptSerializer jss = new JavaScriptSerializer();
TextBox1.Text= jss.Serialize(obj);

在使用JavaScriptSerializer序列化后得到这么个字符串
{"Name":"张三","Birthday":"\/Date(1340693123252)\/"}
因为想要用yyyyMMdd的方式进行序列化输出,因此想到了自定义JavaScriptConverter


public class DateTimeConverter : JavaScriptConverter
{

public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (string.IsNullOrEmpty(dictionary["Value"].ToString()))
return null;

return DateTime.Parse(dictionary["Value"].ToString());
}

public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{

IDictionary<string, object> result = new Dictionary<string, object>();
if (obj == null)
result["Value"] = string.Empty;
else
result["Value"] = ((DateTime)obj).ToString("yyyy-MM-dd HH:mm:ss");
return result;
}

public override IEnumerable<Type> SupportedTypes
{
get { yield return typeof(DateTime); }
}
}


JavaScriptSerializer jss = new JavaScriptSerializer();
jss.RegisterConverters(new JavaScriptConverter[] { new DateTimeConverter() });
TextBox1.Text= jss.Serialize(obj);

序列化后得到这样的结果
{"Name":"张三","BirthDay":{"Value":"2012-06-26 17:11:13"}}

可是反序列化的时候,问题出来了
JavaScriptSerializer jss = new JavaScriptSerializer();
jss.RegisterConverters(new JavaScriptConverter[] { new DateTimeConverter() });
TestAAA obj = jss.Deserialize<TestAAA>(TextBox1.Text);


TestAAA obj = jss.Deserialize<TestAAA>(TextBox1.Text);
这一句报了“未将对象引用设置到对象的实例”的错误

把反序列化代码改成这样,并加上断点
JavaScriptSerializer jss = new JavaScriptSerializer();
jss.RegisterConverters(new JavaScriptConverter[] { new DateTimeConverter() });
object obj = jss.DeserializeObject(TextBox1.Text);
TestAAA a = jss.ConvertToType<TestAAA>(obj);

第3行能正常执行,得到的obj是一个IDictionary<string,object>集合
第4行报“未将对象引用设置到对象的实例”的错误

错误的内部堆栈如下:
System.Web.Script.Serialization.ObjectConverter.ConvertDictionaryToObject(IDictionary`2 dictionary, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject) +1059
System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeInternal(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject) +71
System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeMain(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject) +147
System.Web.Script.Serialization.ObjectConverter.AssignToPropertyOrField(Object propertyValue, Object o, String memberName, JavaScriptSerializer serializer, Boolean throwOnError) +202
System.Web.Script.Serialization.ObjectConverter.ConvertDictionaryToObject(IDictionary`2 dictionary, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject) +1177
System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeInternal(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject) +71
System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeMain(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject) +147
System.Web.Script.Serialization.ObjectConverter.ConvertObjectToType(Object o, Type type, JavaScriptSerializer serializer) +21
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit) +48
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(String input) +70


reflector反进去看了一下,没看出道道来,为啥这个反序列化不行???
...全文
765 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
lkf181 2012-12-12
  • 打赏
  • 举报
回复
你泛型没指定类型吧?
showlin 2012-07-05
  • 打赏
  • 举报
回复
最终用了比较dirty的方法,进行反序列化之前,先用正则对
\/Date(1340693123252)\/这样的字符串进行替换了
licai1210 2012-06-27
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]
to licai1210:

我想我知道你的意思了,按我的自定义序列化方式Birthday变成了一个Dictionary,
那么,如何自定义Converter能自定义序列化成

{"Name":"张三","BirthDay":"2012-06-26 17:11:13"}
这样的方式呢?

因为,如果按你的写法,我还得写一个方法,专门用来转换TestB实例为TestAAA
[/Quote]

对于{"Name":"张三","BirthDay":"2012-06-26 17:11:13"}
我想应该是不需要再添加方法的,能直接转换的。

其实你现在也知道当初为什么报错了,那就可以多去尝试下,找到一个属于自己合适的转换方式就好了。
showlin 2012-06-27
  • 打赏
  • 举报
回复
to licai1210:

我想我知道你的意思了,按我的自定义序列化方式Birthday变成了一个Dictionary,
那么,如何自定义Converter能自定义序列化成

{"Name":"张三","BirthDay":"2012-06-26 17:11:13"}
这样的方式呢?

因为,如果按你的写法,我还得写一个方法,专门用来转换TestB实例为TestAAA
licai1210 2012-06-27
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]
引用 5 楼 的回复:
引用 4 楼 的回复:

对于{"Name":"张三","BirthDay":"2012-06-26 17:11:13"}
我想应该是不需要再添加方法的,能直接转换的。


不行的,一开始我就试过的
JavaScriptSerializer对于datetime类型默认的序列化结果是一个js Date类型的对象

{"Name":"张三","Birthda……
[/Quote]
你既然要这样,那我还是觉得你把Birthday字段设置为string类型好点
showlin 2012-06-27
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
引用 4 楼 的回复:

对于{"Name":"张三","BirthDay":"2012-06-26 17:11:13"}
我想应该是不需要再添加方法的,能直接转换的。

[/Quote]
不行的,一开始我就试过的
JavaScriptSerializer对于datetime类型默认的序列化结果是一个js Date类型的对象

{"Name":"张三","Birthday":"\/Date(1340693123252)\/"}
因此才想到注册一个专门的DateTimeConverter
licai1210 2012-06-26
  • 打赏
  • 举报
回复

public static string str = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
TestAAA obj = new TestAAA
{
Name = "张三",
BirthDay = DateTime.Now
};
JavaScriptSerializer jss = new JavaScriptSerializer();
jss.RegisterConverters(new JavaScriptConverter[] { new DateTimeConverter() });
str = jss.Serialize(obj);
}
else
{
JavaScriptSerializer jss = new JavaScriptSerializer();
jss.RegisterConverters(new JavaScriptConverter[] { new DateTimeConverter() });
object obj = jss.DeserializeObject(str);
TestB a = jss.ConvertToType<TestB>(obj);
}
}

public class TestB
{
public string Name { get; set; }
public Dictionary<string, string> BirthDay { get; set; }
}

其他代码不变,直接测试就好了,你那个类型错误
showlin 2012-06-26
  • 打赏
  • 举报
回复
不是,DeserializeObject方法得到的结果实际上是一个key、value的键值对集合,这个键值对可以正常获取,但是转换成TestAAA的时候报错了,怎么解决?
licai1210 2012-06-26
  • 打赏
  • 举报
回复
{"Name":"张三","BirthDay":{"Value":"2012-06-26 17:11:13"}}
这个反序列得到的不再是TestAAA类型了

object obj = jss.DeserializeObject(TextBox1.Text);
在这里断点的时候你应该能够清晰的看到obj的结构
应该是public class Test
{
public string Name{ get; set; }
public Test2 BirthDay{ get; set; }
}
public class Test2
{
public string Value{ get; set; }
}
这样的
内容概要:本文系统梳理了计算机组成原理的完整知识体系,重点围绕冯·诺依曼体系结构、五大核心硬件(运算器、控制器、存储器、输入/输出设备)、数据表示与运算、存储层级、CPU架构、总线系统及I/O控制机制展开,深入剖析了硬件底层如何支撑Java程序的运行,特别是与JVM内存模型、多线程并发、IO操作、性能调优等关键技术的紧密关联。文章强调通过理解二进制编码、补码运算、缓存机制、指令流水线、乱序执行、中断与DMA等底层原理,帮助Java开发者从根本上解释浮点精度丢失、数值溢出、线程安全、伪共享、IO阻塞等常见问题,并提供性能优化的硬件级视角。; 适合人群:具备一定Java开发基础,工作1-3年,希望深入理解JVM、并发编程、IO模型底层原理的后端研发人员。; 使用场景及目标:① 理解Java代码从编译到执行的完整软硬件链路;② 掌握JVM内存布局、GC机制、线程上下文切换、volatile与synchronized的硬件实现原理;③ 分析并解决高并发、高性能场景下的性能瓶颈,如缓存命中率低、伪共享、总线争用、IO阻塞等问题;④ 在面试中清晰阐述Java底层与计算机硬件的关联,展现扎实的系统功底。; 阅读建议:建议按照文档提供的“八、学习顺序”分阶段学习,每学完一个硬件模块,立即结合对应的Java技术点(如学到Cache思考伪共享和@Contended)进行复盘,将抽象硬件原理具象化到日常开发场景中,以达到学以致用的目的。

62,271

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧