JMS队列JSON字符串适配多POJO类的Gson转换技术问询
解决方案:根据JSON自动匹配POJO并完成数据库插入
这种场景我之前做项目时也碰到过,核心思路是先判断JSON对应的POJO类型,再做反序列化和入库操作。下面给你几个实用的实现方案,按推荐程度排序:
方案1:给JSON添加类型标识字段(最推荐)
这是最清晰、最不易出错的方式——要求发送到JMS队列的JSON统一携带一个type字段,用来标记它属于哪个表的POJO,比如"type":"book"对应BooksTable,"type":"transaction"对应交易表POJO(比如TransactionTable)。
代码示例:
String msg = "{\"type\":\"book\",\"id\":\"4\",\"item\":\"GOT\",\"description\":\"hello\"}"; Gson gson = new Gson(); // 先解析成JsonObject,读取类型标识 JsonObject jsonObject = gson.fromJson(msg, JsonObject.class); String dataType = jsonObject.get("type").getAsString(); // 根据类型匹配对应的POJO并入库 switch(dataType) { case "book": BooksTable book = gson.fromJson(jsonObject, BooksTable.class); addBook(book); break; case "transaction": TransactionTable transaction = gson.fromJson(jsonObject, TransactionTable.class); addTransaction(transaction); // 假设这是交易表的插入方法 break; default: // 处理未知类型,比如打日志或抛出异常 throw new IllegalArgumentException("Unsupported JSON type: " + dataType); }
方案2:通过特征字段判断POJO类型
如果无法修改JMS发送的JSON结构(不能加type字段),可以通过POJO特有的字段来判断。比如BooksTable有item和description字段,而交易表有transactionId和amount字段,就可以检查这些特征字段的存在性。
代码示例:
String msg = "{\"id\":\"4\",\"item\":\"GOT\",\"description\":\"hello\"}"; Gson gson = new Gson(); JsonObject jsonObject = gson.fromJson(msg, JsonObject.class); // 检查BooksTable的特征字段 if (jsonObject.has("item") && jsonObject.has("description")) { BooksTable book = gson.fromJson(jsonObject, BooksTable.class); addBook(book); } // 检查交易表的特征字段 else if (jsonObject.has("transactionId") && jsonObject.has("amount")) { TransactionTable transaction = gson.fromJson(jsonObject, TransactionTable.class); addTransaction(transaction); } // 处理无法识别的JSON else { System.err.println("Failed to match JSON to any POJO: " + msg); }
⚠️ 注意:如果两个POJO有重叠的字段,这种方法可能会误判,所以只适合字段差异明显的场景。
方案3:自定义Gson反序列化器(优雅进阶版)
如果想让类型判断逻辑更内聚,可以自定义Gson的TypeAdapterFactory,把类型判断和反序列化逻辑封装在一起,代码更整洁。
实现步骤:
- 先定义一个父类,让
BooksTable和TransactionTable都继承它(比如TableBase) - 编写自定义的
TypeAdapterFactory,在反序列化时自动判断类型并返回对应的POJO实例
代码示例:
// 1. 定义父类 public abstract class TableBase {} // 2. 让POJO继承父类 public class BooksTable extends TableBase { // 原有的id、item、description字段及getter/setter } public class TransactionTable extends TableBase { // 交易表的字段及getter/setter } // 3. 自定义TypeAdapterFactory public class TableTypeAdapterFactory implements TypeAdapterFactory { @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { // 只处理TableBase的子类 if (!TableBase.class.isAssignableFrom(type.getRawType())) { return null; } final TypeAdapter<JsonObject> jsonObjAdapter = gson.getAdapter(JsonObject.class); final TypeAdapter<BooksTable> bookAdapter = gson.getAdapter(BooksTable.class); final TypeAdapter<TransactionTable> transAdapter = gson.getAdapter(TransactionTable.class); return new TypeAdapter<T>() { @Override public void write(JsonWriter out, T value) throws IOException { // 序列化逻辑(如果需要的话) if (value instanceof BooksTable) { bookAdapter.write(out, (BooksTable) value); } else if (value instanceof TransactionTable) { transAdapter.write(out, (TransactionTable) value); } } @Override public T read(JsonReader in) throws IOException { JsonObject jsonObj = jsonObjAdapter.read(in); // 这里可以用type字段或特征字段判断 if (jsonObj.has("type") && "book".equals(jsonObj.get("type").getAsString())) { return (T) bookAdapter.fromJsonTree(jsonObj); } else if (jsonObj.has("transactionId")) { return (T) transAdapter.fromJsonTree(jsonObj); } throw new IOException("Unknown table type for JSON: " + jsonObj); } }; } } // 4. 使用自定义Factory Gson gson = new GsonBuilder() .registerTypeAdapterFactory(new TableTypeAdapterFactory()) .create(); // 统一处理反序列化和入库 TableBase table = gson.fromJson(msg, TableBase.class); if (table instanceof BooksTable) { addBook((BooksTable) table); } else if (table instanceof TransactionTable) { addTransaction((TransactionTable) table); }
内容的提问来源于stack exchange,提问作者Shubham Chopra
相关产品推荐
相关产品推荐

