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

Java对象转JSON触发JsonIOException,自定义XMLGregorianCalendar TypeAdapter无效

解决XMLGregorianCalendar转JSON失败问题

问题背景

已为XMLGregorianCalendar接口编写自定义TypeAdapter,但转换包含该类型的Java对象到JSON时仍抛出权限异常,代码及错误栈如下:

问题代码

package com;

import java.io.IOException;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

public class DateConversion {

    public static void main(String[] args) throws DatatypeConfigurationException {

        XMLGregorianCalendar date = DatatypeFactory.newInstance().newXMLGregorianCalendar();

        Request req = new Request();
        req.setDate(date);
        TypeAdapter<XMLGregorianCalendar> adapter = new TypeAdapter<XMLGregorianCalendar>() {

            @Override
            public void write(JsonWriter writer, XMLGregorianCalendar value) throws IOException {
                System.out.println("Inside write");
                if(value==null) {
                    writer.nullValue();
                    return;
                }
                writer.value("value");

            }

            @Override
            public XMLGregorianCalendar read(JsonReader reader) throws IOException {
                System.out.println("Inside read");
                return null;
            }
        };
        Gson gsonBuilder = (new GsonBuilder()).registerTypeAdapter(XMLGregorianCalendar.class, adapter).serializeNulls().create();
        System.out.println(gsonBuilder.toJson(req));
    }

}

class Request {
    private XMLGregorianCalendar date;

    public XMLGregorianCalendar getDate() {
        return date;
    }

    public void setDate(XMLGregorianCalendar date) {
        this.date = date;
    }
}

错误栈

Exception in thread "main" com.google.gson.JsonIOException: Failed making field 'com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl#eon' accessible; either change its visibility or write a custom TypeAdapter for its declaring type

错误原因

XMLGregorianCalendar是接口,通过DatatypeFactory创建的实例实际是其内部实现类XMLGregorianCalendarImpl。使用registerTypeAdapter仅会为精确匹配的XMLGregorianCalendar类型注册适配器,Gson处理实际对象时会尝试反射访问XMLGregorianCalendarImpl的私有字段,触发权限异常。

解决方法

将registerTypeAdapter替换为registerTypeHierarchyAdapter,该方法会为目标类型及其所有子类/实现类注册适配器,确保Gson处理XMLGregorianCalendarImpl时使用自定义适配器而非反射:

修改后的Gson构建代码:

Gson gsonBuilder = new GsonBuilder()
    .registerTypeHierarchyAdapter(XMLGregorianCalendar.class, adapter)
    .serializeNulls()
    .create();

验证效果

修改后运行代码,控制台会输出Inside write,并打印出正确的JSON结果:

{"date":"value"}

内容的提问来源于stack exchange,提问作者A Hybris Dev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 18:45:22