如何使用自定义转换器?XML时间转Long解析异常排查
解决Retrofit 1.9 + SimpleXML自定义转换器不生效的问题
看起来你的核心问题是SimpleXML没有加载到自定义的TimeConverter,导致直接尝试把HH:mm:ss字符串转成Long类型抛出异常。下面是一步步的解决方法:
1. 确保自定义转换器的实现正确
先确认你的TimeConverter符合SimpleXML的要求,这里给一个标准实现示例供参考:
public class TimeConverter implements Converter<Long> { private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); @Override public Long read(InputNode node) throws Exception { try { String timeStr = node.getValue(); Date date = TIME_FORMAT.parse(timeStr); // 注意:如果需要当天的时间戳,要结合当前日期(否则默认是1970年的时间) Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, date.getHours()); calendar.set(Calendar.MINUTE, date.getMinutes()); calendar.set(Calendar.SECOND, date.getSeconds()); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTimeInMillis(); } catch (ParseException e) { e.printStackTrace(); return 0L; // 或者抛出自定义业务异常 } } @Override public void write(OutputNode node, Long value) throws Exception { if (value == null) { node.setValue("00:00:00"); return; } Date date = new Date(value); node.setValue(TIME_FORMAT.format(date)); } }
2. 自定义SimpleXMLConverter,注册转换器
Retrofit 1.9默认的SimpleXMLConverter没有启用转换器支持,需要我们手动构建带有转换器注册表的Serializer:
public class CustomSimpleXMLConverter extends SimpleXMLConverter { @Override protected Serializer createSerializer() { // 创建注册表并添加自定义转换器 Registry registry = new Registry(); try { // 将TimeConverter绑定到Long类型,让SimpleXML识别 registry.bind(Long.class, TimeConverter.class); } catch (Exception e) { throw new RuntimeException("注册转换器失败", e); } // 创建匹配器,关联注册表 RegistryMatcher matcher = new RegistryMatcher(); matcher.setRegistry(registry); // 创建Serializer并启用转换器、宽松解析模式 Serializer serializer = new Persister(matcher); serializer.setStrict(false); return serializer; } }
3. 修改Retrofit配置,使用自定义Converter
把原来的默认SimpleXMLConverter替换成我们自定义的实现:
OkHttpClient httpClient = new OkHttpClient(); RestAdapter.Builder builder = new RestAdapter.Builder(); builder.setEndpoint(url); builder.setLogLevel(RestAdapter.LogLevel.FULL); // 替换为自定义的转换器 builder.setConverter(new CustomSimpleXMLConverter()); builder.setClient(new OkClient(httpClient)); RestAdapter restAdapter = builder.build(); ChansonApi api = restAdapter.create(ChansonApi.class);
4. 检查Item类的注解规范
确保你的Item类注解配置正确,尤其是无参构造和注解的位置:
@Root(strict = false) private static class Item { @Element(name = "time") @Convert(TimeConverter.class) // 注解要和@Element配合使用 private Long time; // SimpleXML必须要有无参构造函数 public Item() {} // 添加getter/setter让框架可以访问字段 public Long getTime() { return time; } public void setTime(Long time) { this.time = time; } }
问题根源说明
Retrofit 1.9默认的SimpleXMLConverter创建的Serializer没有配置RegistryMatcher,导致SimpleXML无法识别@Convert注解,会直接尝试把XML字符串值强转成Long类型,从而抛出NumberFormatException,根本不会触发你的自定义转换器。通过自定义SimpleXMLConverter注册转换器并启用转换功能,就能让框架正确调用TimeConverter处理时间字符串了。
内容的提问来源于stack exchange,提问作者Yarh
相关产品推荐
相关产品推荐

