使用Gson反序列化SQS消息时Timestamp字段解析失败
问题根源
核心问题出在嵌套的Message字段内容不是标准JSON:Timestamp的值是裸日期字符串(2023-06-18T19:36:43.219Z),但JSON规范要求字符串必须用双引号包裹。哪怕你不需要这个字段,Gson解析时也会因为JSON结构不合法直接报错,根本到不了“忽略字段”那一步。
解决思路
既然不能改原消息结构,那就先在代码里把嵌套的非标准JSON修复成合法格式,再进行反序列化,同时让Gson自动忽略不需要的字段。
具体步骤
- 修复JSON格式:用正则表达式给
Timestamp的裸日期值加上双引号,将非标准JSON转为合法格式。 - 配置Gson忽略未知字段:明确指定忽略
WorkId、MsgFormatVer这类POJO中未定义的字段,避免干扰反序列化。
完整代码实现
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.util.regex.Matcher; import java.util.regex.Pattern; public class SQSMessageParser { // 配置Gson:兼容宽松格式、明确忽略未知字段 private static final Gson gson = new GsonBuilder() .setLenient() .setIgnoreUnknownProperties(true) .create(); // 正则匹配Timestamp字段,精准定位需要修复的内容 private static final Pattern TIMESTAMP_FIX_PATTERN = Pattern.compile("(Timestamp:)(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z)"); public static <T> T parseSQSMessage(final String rawMessage, final Class<T> targetClass) { // 第一步:解析外层结构,拿到嵌套的非标准JSON字符串 EventModel outerModel = gson.fromJson(rawMessage, EventModel.class); String nestedMsg = outerModel.getMessage(); // 第二步:修复Timestamp字段,给日期值添加双引号 Matcher matcher = TIMESTAMP_FIX_PATTERN.matcher(nestedMsg); if (matcher.find()) { nestedMsg = matcher.replaceFirst("$1\"$2\""); } // 第三步:反序列化修复后的合法JSON return gson.fromJson(nestedMsg, targetClass); } // 原POJO保持不变,添加getter/setter方便取值 public static class EventModel { private String Message; public String getMessage() { return Message; } public void setMessage(String message) { Message = message; } } public static class SQSMessageBody { private String ObjectId; public String getObjectId() { return ObjectId; } public void setObjectId(String objectId) { ObjectId = objectId; } } // 测试示例 public static void main(String[] args) { String sqsRawBody = "{\"Message\":\"{ObjectId:\\\"SomeObjectId:SomeVersion:1\\\",WorkId:\\\"12345abcdde\\\",Timestamp:2023-06-18T19:36:43.219Z,MsgFormatVer:1}\"}"; SQSMessageBody result = parseSQSMessage(sqsRawBody, SQSMessageBody.class); System.out.println("解析得到的ObjectId:" + result.getObjectId()); } }
关键点说明
- 正则表达式专门匹配你给出的Timestamp格式,只会修改目标字段,不会影响其他内容。
setLenient()用于兼容可能存在的其他轻微非标准JSON语法,配合正则修复后稳定性更高。setIgnoreUnknownProperties(true)明确指定忽略未知字段,避免后续消息新增字段时出现反序列化异常。
内容的提问来源于stack exchange,提问作者Ravi Keshri
相关产品推荐
相关产品推荐

