使用GSON解析值可能为自定义对象或字符串的JSON方案
Gson 兼容多类型字段解析方案
你完全不需要全量手动调用JsonParser解析所有字段,通过Gson自定义反序列化器即可实现POJO层面的通用解析,兼容key_four的两种值类型。
实现步骤
- 首先定义顶层响应POJO,固定类型的字段直接声明对应类型,类型不固定的
key_four先声明为Object类型即可:
// 顶层响应POJO public class WsSubscribeResponse { private KeyOneEnum key_one; // 你已定义的对应枚举类 private String key_two; private String key_three; private Object key_four; // 不指定固定类型,反序列化时按规则赋值 // 自行补充各字段的getter、setter方法 }
- 编写自定义反序列化器,逻辑中先读取
key_one的枚举值,根据枚举值判断key_four的实际类型,再做对应解析:
import com.google.gson.*; import java.lang.reflect.Type; public class WsResponseDeserializer implements JsonDeserializer<WsSubscribeResponse> { @Override public WsSubscribeResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject root = json.getAsJsonObject(); WsSubscribeResponse resp = new WsSubscribeResponse(); // 先解析类型固定的三个字段,直接复用Gson默认解析逻辑 resp.setKey_one(context.deserialize(root.get("key_one"), KeyOneEnum.class)); resp.setKey_two(root.get("key_two").getAsString()); resp.setKey_three(root.get("key_three").getAsString()); // 根据key_one枚举值判断key_four的目标类型 JsonElement keyFourEle = root.get("key_four"); KeyOneEnum sceneEnum = resp.getKey_one(); // 这里替换成你实际的枚举判断逻辑,对应10%的字符串场景 if (sceneEnum.equals(KeyOneEnum.KEY_FOUR_IS_STRING)) { resp.setKey_four(keyFourEle.getAsString()); } else { // 剩余90%场景解析为你已经定义好的KeyFour业务POJO resp.setKey_four(context.deserialize(keyFourEle, KeyFourPOJO.class)); } return resp; } }
- 初始化Gson实例时注册上述自定义反序列化器,后续所有Websocket推送的消息都可以直接用这个Gson实例反序列化,不需要额外手动处理:
Gson gson = new GsonBuilder() .registerTypeAdapter(WsSubscribeResponse.class, new WsResponseDeserializer()) .create(); // 直接反序列化即可 WsSubscribeResponse response = gson.fromJson(websocketPushJsonStr, WsSubscribeResponse.class);
方案说明
- 不推荐全量使用
JsonParser().parse(jsonString).getAsJsonObject()手动解析:这种方式需要逐字段写取值、类型转换逻辑,代码冗余度高,后续字段调整时维护成本高,容易出现字段名拼写错误、类型转换异常。 - 自定义反序列化器方案仅需要处理类型不固定的
key_four字段,其余固定类型字段全部复用Gson成熟的默认解析逻辑,代码量小,可维护性强。如果后续key_four新增其他类型,只需要在反序列化器中增加对应枚举的判断分支即可,不需要改动其他解析逻辑。
小提示:如果需要强类型约束,也可以给
key_four定义一个包装类,内部分别持有字符串类型、自定义POJO类型的属性,反序列化时按场景给对应属性赋值,避免后续使用时频繁做类型判断。
内容的提问来源于stack exchange,提问作者Zander
相关产品推荐
相关产品推荐

