错误描述:
在springboot
中,使用进行net.sf.json.JSONObject.fromObject(javaObject)
进行json
序列化时,得到错误Caused by:java.lang.IllegalArgumentException at java.sql.Date.getHours(Date.java:187)
。
最终解决方案:自定义转换器,并注入至转换方法。
我们解决问题的顺序如下:
- 翻译
- 依据翻译和现实情况,尝试解决问题。
- 看官方文档,或是方法描述,尝试解决问题。
-
google
相关关键字,解决问题。
翻译
由以下异常引起:在java.sql.Date.getHours
方法上(该方法位于Data.java的187行
)发生了java.lang.IllegalArgumentException
异常。
其中:Illegal
:非法的, Argument
:论据
现实情况
现实情况是我们并没有主动调用这个getHour()
方法,所以猜想,应该是net.sf.json.JSONObject.fromObject(javaObject)
进行json
序列化时,主动调用了该方法。
通过打断点的方式,我们在fromObject(javaObject)
本行A、下一行B、java.sql.Date.getHours
的187行C,分别打一个断点,最终发现执行顺序为:A->C->异常。符合我们的猜想预期。
如果是A->B->C->异常,则说明并不是由A触发的C,也就证明我们的猜想是错误的。你可以参与下文来快速的找到执行过程。
原因找到了,但无论是net.sf.json.JSONObject.fromObject(javaObject)
还是java.sql.Date.getHours
,都不是我们自已维护的。所以得到结论:两者在进行配合时发生了冲突,当前解决方法则只能弃用一方,或是向一方注入配置,来绕过java.sql.Date.getHours
方法的调用。
看方法描述
我们找到java.sql.Date.getHours()
方法:
/**
* This method is deprecated and should not be used because SQL Date
* values do not have a time component.
*
* @deprecated
* @exception java.lang.IllegalArgumentException if this method is invoked
* @see #setHours
*/
@Deprecated
public int getHours() {
throw new java.lang.IllegalArgumentException();
}
基本的意思就是说,这个方法已经弃用了,因为:sql.Date
只是精确到日
,根本就没有hour
这说,所以你想得到小时,这当然不行了。原来问题出在net.sf.json.JSONObject.fromObject(javaObject)
上,当其转换sql.Date
时,调用了不该调用已弃的getHour()
方法,所以触发了这个异常。
结论:好像谁都没有错。第一个的原则是:只要你有getXXX()
我就调用,保证对所有的get
方法全部序列化。第二个的原则是:虽然我历史上有过getHour()
方法,但是这个方法根本就不应该被调用,我的最小精确度是天
,你问我是几小时,我哪知道,所以你调用我,我就报出异常。
按我们以往的经验,一些牛气的第三方库,是会给用户提供一些重写的接口的接口的,比如我们在项目启动时,向net.sf.json
的特定接口,注入一个Bean
,该Bean
的作用是:重写sql.Date
的json
序列化方法。
在相关资料的学习中,并没有找到统一配置的路径。但是可以在转换前,定义JsonConfig
,并将自定义的转换器装配进行。但我认为每次都这样新建一个转换器,太麻烦了。所以后面,又尝试了一些其它的方法,最后,没有办法,其它的方法都是曲线救国,最终还是绕到了定义转换器的路上来了。
实际开发中,我还尝试使用排除@Deprecated
的方法,该方法会得到一个其它的我们不想得到的结果,不再详细阐述;已尝试了将sql.Date换成util.Date,虽然能够序列化,但序列化后的内容并不是我们想要的,进行请求数据绑定时,会得到400错误,不在阐述
使用转换器前:
JSONObject jsonObject = JSONObject.fromObject(mandatoryInstrument);
使用转换器后:
jsonConfig = new JsonConfig();
jsonConfig.registerJsonValueProcessor(Date.class, new JsonValueProcessor() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd");
@Override
public Object processArrayValue(Object o, JsonConfig jsonConfig) {
return simpleDateFormat.format(o);
}
@Override
public Object processObjectValue(String s, Object o, JsonConfig jsonConfig) {
if (o != null) {
return simpleDateFormat.format(o);
} else {
return null;
}
}
});
JSONObject jsonObject = JSONObject.fromObject(mandatoryInstrument, jsonConfig);
结论
在学习一门新技术的时候或是新的问题的时候,上来直接看官方文档是不现实的,需要结合google
找到关键点,然后再结合关键点来学习特定的官方文档,最后达到解决问题并且能够理解自己所解决问题的根本原因的目的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。