Gson反序列化日期报错JsonSyntaxException/ParseException求助
嗨,我知道你折腾了好几个小时都没搞定这个问题,别急,咱们一步步来排查!
首先,你遇到的com.google.gson.JsonSyntaxException: 2020-08-30错误,看起来是Gson在解析日期列表时没有正确使用你配置的日期格式,或者是泛型类型处理出了问题,我给你几个针对性的解决方案:
1. 先排查JSON内容是否正确
你的文件读取逻辑里,处理"END"标记时的删除操作可能有问题:
fileContent.delete(fileContent.length() - 4, fileContent.length());
如果你的"END"行是纯文本END(3个字符),加上之前append的\n,总共是4个字符(\nEND),这个删除操作是对的,但如果你的"END"行带有空格(比如END),trim后匹配但实际字符串长度不止3,就会导致JSON内容被错误截断,间接引发解析报错。
建议你在调用fromJson之前,先打印fileContent.toString(),确认生成的JSON是完整且格式正确的(比如你的示例{"freeDates": ["2020-08-30", "2020-08-31", "2020-09-01", "2020-09-02"]})。
2. 确保泛型类型被正确识别
因为Java泛型擦除的问题,你的GenericRepository中的type参数可能没有正确获取到实体类的泛型信息(比如List<Date>的实际类型)。如果你的GenericRepository是通过Class<T>来传递类型的,Gson无法识别实体类内部的List<Date>泛型,会用默认的日期解析逻辑,忽略你配置的setDateFormat。
解决方法是在GenericRepository中通过ParameterizedType获取正确的泛型类型:
public abstract class GenericRepository<T> { protected final Type type; protected GenericRepository() { // 获取父类的泛型参数 Type superclass = getClass().getGenericSuperclass(); if (superclass instanceof ParameterizedType) { this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0]; } else { throw new IllegalArgumentException("GenericRepository必须使用泛型子类"); } } // 你的getAllEntities方法... }
这样当你继承GenericRepository时(比如class BookingRepository extends GenericRepository<Booking>),type就会是Booking的完整泛型类型,Gson就能正确识别List<Date>字段。
3. 自定义Date TypeAdapter强制解析格式
如果上面的方法还是不行,那我们直接给Date类型写一个自定义的解析器,绕过Gson默认的集合处理逻辑:
第一步:编写DateTypeAdapter
import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class DateTypeAdapter extends TypeAdapter<Date> { // 固定日期格式 private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); @Override public void write(JsonWriter out, Date value) throws IOException { if (value == null) { out.nullValue(); return; } out.value(dateFormat.format(value)); } @Override public Date read(JsonReader in) throws IOException { if (in.peek() == com.google.gson.JsonToken.NULL) { in.nextNull(); return null; } String dateStr = in.nextString(); try { return dateFormat.parse(dateStr); } catch (ParseException e) { throw new com.google.gson.JsonSyntaxException("无法解析日期: " + dateStr, e); } } }
第二步:注册到GsonBuilder
修改你的Gson实例构建代码,替换setDateFormat为注册自定义Adapter:
private static Gson g = new GsonBuilder() .registerTypeAdapter(Date.class, new DateTypeAdapter()) .setPrettyPrinting() .serializeNulls() .create();
这个方法会强制Gson用我们指定的格式解析所有Date类型(包括List里的Date),彻底避免格式不匹配的问题。
你可以先试试第三个方法,通常这个方案能直接解决日期列表的解析问题,要是还有问题,再回头检查JSON内容和泛型类型的传递~
内容的提问来源于stack exchange,提问作者Vasilije Bursac

