使用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反进去看了一下,没看出道道来,为啥这个反序列化不行???
...全文
688 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; }
}
这样的

62,047

社区成员

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

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

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

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