You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用自定义转换器?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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:23:57