执行Java代码时触发java.lang.RuntimeException:无法序列化数字/日期问题求助
解决ksoap2中java.lang.RuntimeException序列化失败问题
我来帮你搞定这两个ksoap2序列化报错的问题!这俩错误本质都是SoapSerializationEnvelope对特定数据类型的默认支持不足导致的,咱们逐个拆解解决:
1. 错误:java.lang.RuntimeException: Cannot serialize: 12.5
问题根源
你直接传递了Double类型的数值,但ksoap2需要明确绑定数据类型,默认情况下直接传递原始包装类值可能会触发序列化逻辑异常。
解决办法
用PropertyInfo明确指定参数的类型,让ksoap2清楚该怎么处理这个数值:
// 假设你的请求对象是request,参数名对应服务端的"amount" SoapObject request = new SoapObject(YOUR_NAMESPACE, YOUR_METHOD_NAME); PropertyInfo amountInfo = new PropertyInfo(); amountInfo.setName("amount"); // 服务端定义的参数名 amountInfo.setValue(12.5); amountInfo.setType(Double.class); // 明确标注数据类型 request.addProperty(amountInfo);
2. 错误:序列化Date对象失败(日志栈显示Cannot serialize: Thu Jan 01 00:40:00 GMT+05:30 1970)
问题根源
ksoap2默认不支持java.util.Date对象的直接序列化——SOAP协议没有统一的Date类型标准,需要咱们手动转换格式或自定义序列化逻辑。
解决办法(两种可选)
办法一:转成时间戳传递(最简单高效)
把Date对象转成毫秒级时间戳(Long类型),服务端再根据时间戳还原成Date即可:
Date targetDate = new Date(yourTimestamp); request.addProperty("targetDate", targetDate.getTime()); // 传递时间戳数值
办法二:注册自定义Date序列化器(适配标准日期格式)
如果服务端期望的是ISO 8601这类标准日期字符串,可以自定义序列化器并注册到Envelope:
首先创建序列化器类:
public class DateSerializer implements KvmSerializable { private Date date; public DateSerializer() {} public DateSerializer(Date date) { this.date = date; } @Override public Object getProperty(int index) { return date; } @Override public int getPropertyCount() { return 1; } @Override public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info) { info.name = "date"; info.type = Date.class; } @Override public void setProperty(int index, Object value) { date = (Date) value; } @Override public void write(XmlSerializer writer) throws IOException { // 转成SOAP兼容的ISO 8601格式字符串 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); writer.text(sdf.format(date)); } @Override public void read(XmlPullParser parser) throws IOException, XmlPullParserException { // 如果需要反序列化,在这里实现读取逻辑 String dateStr = parser.nextText(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); try { date = sdf.parse(dateStr); } catch (ParseException e) { throw new IOException(e.getMessage()); } } }
然后在创建Envelope时注册这个序列化器:
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); // 替换成你的接口命名空间和对应的类型标识 envelope.addMapping(YOUR_NAMESPACE, "Date", Date.class, new DateSerializer()); // 添加参数时用自定义序列化器包装 request.addProperty(new PropertyInfo() {{ setName("targetDate"); setValue(new DateSerializer(targetDate)); setType(Date.class); }});
通用注意事项
- 所有传递给SoapObject的参数,尽量用
PropertyInfo明确指定类型,避免依赖ksoap2的自动推断; - 对于非ksoap2默认支持的类型(比如自定义Bean、Date),一定要注册对应的序列化器;
- 提前和服务端确认参数类型要求,确保客户端传递的类型和服务端预期一致(比如服务端是
double还是Double,是日期字符串还是时间戳)。
内容的提问来源于stack exchange,提问作者Abhinav Sindhu
相关产品推荐
相关产品推荐

