如何将Gson JsonObject转换为Avro自动生成的ModernCustomer类
解决方案:Gson JsonObject 转 Avro 生成的 ModernCustomer 类
问题回顾
通过niceservice.nicemethod()获取到Gson的JsonObject,结构如下:
{ "Customer": { "name": "John Doe", "gender": "Male" }, "AdditioanInfo": { "samplefield1": "sampleValue1", "samplefield2": "sampleValue2", "samplefield3": "sampleValue3", "SubAdditionalInfo": { "SubAdditionalInfo1": "SubAdditionalValue1", "SubAdditionalInfo2": "SubAdditionalValue2", "SubAdditionalInfo3": "SubAdditionalValue3", "SubSubInfo": { "SubSubInfo1" : "SubSubInfoValue1", "SubSubInfo2" : "SubSubInfoValue2", "SubSubInfo3" : "SubSubInfoValue3" } }, "ExtraInfo": { "ExtraInfo1" : "Extravalue1", "ExtraInfo2" : "Extravalue2" } } }
已通过Avro schema生成ModernCustomer类,尝试Jackson转换失败,需要在第三方库受限的情况下完成赋值。
方法一:Avro原生JSON反序列化(推荐)
Avro生成的类自带原生JSON解析支持,无需额外依赖(项目已引入Avro基础依赖):
import org.apache.avro.io.DecoderFactory; import org.apache.avro.io.JsonDecoder; import org.apache.avro.specific.SpecificDatumReader; // 从Gson JsonObject获取JSON字符串 String jsonContent = mdata.toString(); // 初始化Avro读取器和JSON解码器 SpecificDatumReader<ModernCustomer> datumReader = new SpecificDatumReader<>(ModernCustomer.class); JsonDecoder decoder = DecoderFactory.get().jsonDecoder(ModernCustomer.SCHEMA$, jsonContent); // 反序列化生成对象 ModernCustomer modernCustomer = datumReader.read(null, decoder);
方法二:用Gson直接映射(已有Gson依赖时使用)
既然已经在使用Gson的JsonObject,直接用Gson完成反序列化最省事:
import com.google.gson.Gson; // 方法1:直接从JsonObject转换 Gson gson = new Gson(); ModernCustomer modernCustomer = gson.fromJson(mdata, ModernCustomer.class); // 方法2:从JSON字符串转换(效果一致) // ModernCustomer modernCustomer = gson.fromJson(mdata.toString(), ModernCustomer.class);
方法三:手动遍历赋值(无额外序列化库时使用)
如果第三方库使用严格受限,可手动遍历JsonObject的每个字段,通过Avro生成的Builder模式逐层构建对象:
import com.google.gson.JsonObject; // 1. 构建Customer对象 JsonObject customerJson = mdata.getAsJsonObject("Customer"); ModernCustomer.Customer customer = ModernCustomer.Customer.newBuilder() .setName(customerJson.get("name").getAsString()) .setGender(customerJson.get("gender").getAsString()) .build(); // 2. 构建最内层的SubSubInfo JsonObject subSubInfoJson = mdata.getAsJsonObject("AdditioanInfo") .getAsJsonObject("SubAdditionalInfo") .getAsJsonObject("SubSubInfo"); ModernCustomer.AdditioanInfo.SubAdditionalInfo.SubSubInfo subSubInfo = ModernCustomer.AdditioanInfo.SubAdditionalInfo.SubSubInfo.newBuilder() .setSubSubInfo1(subSubInfoJson.get("SubSubInfo1").getAsString()) .setSubSubInfo2(subSubInfoJson.get("SubSubInfo2").getAsString()) .setSubSubInfo3(subSubInfoJson.get("SubSubInfo3").getAsString()) .build(); // 3. 构建SubAdditionalInfo JsonObject subAdditionalInfoJson = mdata.getAsJsonObject("AdditioanInfo") .getAsJsonObject("SubAdditionalInfo"); ModernCustomer.AdditioanInfo.SubAdditionalInfo subAdditionalInfo = ModernCustomer.AdditioanInfo.SubAdditionalInfo.newBuilder() .setSubAdditionalInfo1(subAdditionalInfoJson.get("SubAdditionalInfo1").getAsString()) .setSubAdditionalInfo2(subAdditionalInfoJson.get("SubAdditionalInfo2").getAsString()) .setSubAdditionalInfo3(subAdditionalInfoJson.get("SubAdditionalInfo3").getAsString()) .setSubSubInfo(subSubInfo) .build(); // 4. 构建ExtraInfo JsonObject extraInfoJson = mdata.getAsJsonObject("AdditioanInfo") .getAsJsonObject("ExtraInfo"); ModernCustomer.AdditioanInfo.ExtraInfo extraInfo = ModernCustomer.AdditioanInfo.ExtraInfo.newBuilder() .setExtraInfo1(extraInfoJson.get("ExtraInfo1").getAsString()) .setExtraInfo2(extraInfoJson.get("ExtraInfo2").getAsString()) .build(); // 5. 构建AdditioanInfo JsonObject additioanInfoJson = mdata.getAsJsonObject("AdditioanInfo"); ModernCustomer.AdditioanInfo additioanInfo = ModernCustomer.AdditioanInfo.newBuilder() .setSamplefield1(additioanInfoJson.get("samplefield1").getAsString()) .setSamplefield2(additioanInfoJson.get("samplefield2").getAsString()) .setSamplefield3(additioanInfoJson.get("samplefield3").getAsString()) .setSubAdditionalInfo(subAdditionalInfo) .setExtraInfo(extraInfo) .build(); // 6. 构建最终的ModernCustomer对象 ModernCustomer modernCustomer = ModernCustomer.newBuilder() .setCustomer(customer) .setAdditioanInfo(additioanInfo) .build();
为什么Jackson转换失败?
Avro生成的类默认使用Builder模式,且字段映射规则和Jackson默认逻辑不兼容,若要使用Jackson需额外引入jackson-datatype-avro模块,但这不符合你第三方库受限的需求,因此不推荐。
内容的提问来源于stack exchange,提问作者Shreyas
相关产品推荐
相关产品推荐

