JsonAvroConverter转换数组JSON报START_ARRAY反序列化LinkedHashMap异常
报错原因
报错由两个问题共同导致:
- 方法调用不匹配:
convertToGenericDataRecord方法仅适用于根节点为record类型的Avro schema转换,该方法反序列化时期待输入的JSON根节点是对象结构(对应START_OBJECT token,反序列化为LinkedHashMap),但传入的JSON根节点是数组结构(对应START_ARRAY token),直接触发类型不匹配异常。 - 存在隐藏的类型定义不匹配问题:定义的schema中
id字段类型为string,但示例JSON里的id是数值类型,就算解决了方法调用问题,后续也会抛出类型转换错误。
解决方案
根据实际业务场景二选一即可:
场景1:保持现有JSON数组结构不变
- 替换转换方法:根schema为array类型时,调用
convertToGenericDataArray方法完成转换,该方法返回GenericData.Array<GenericData.Record>类型的结果,适配数组结构输入。 - 修正类型定义:将schema中
id字段的类型从string改为int/long,和JSON中的数值类型匹配;如果业务上id确实是字符串类型,就把JSON里的id值改为带双引号的字符串格式(比如{"id":"1"})。
修正后的可运行代码示例:
String json = "[{\"id\":1},{\"id\":2},{\"id\":3}]"; String schemaStr = "{" + " \"type\" : \"array\"," + " \"items\" : {\"type\":\"record\",\"name\":\"ids\", \"fields\":[{ \"name\" : \"id\", \"type\" : \"int\" }]}" + "}"; JsonAvroConverter converter = new JsonAvroConverter(); Schema schema = new Schema.Parser().parse(schemaStr); // 调用数组专用转换方法 GenericData.Array<GenericData.Record> recordList = converter.convertToGenericDataArray(json.getBytes(), schema);- 替换转换方法:根schema为array类型时,调用
场景2:必须使用
convertToGenericDataRecord方法
该方法要求根schema必须是record类型,需要调整schema结构,将数组作为record的一个字段存在,同时对应调整JSON结构为外层包裹对象的格式:// 调整后的schema,根为record类型 String wrappedSchemaStr = "{" + " \"type\":\"record\",\"name\":\"IdList\"," + " \"fields\":[{" + " \"name\":\"items\"," + " \"type\":{\"type\":\"array\",\"items\":{\"type\":\"record\",\"name\":\"ids\",\"fields\":[{\"name\":\"id\",\"type\":\"int\"}]}}" + " }]" + "}"; // 调整后的对应JSON,外层为对象 String wrappedJson = "{\"items\":[{\"id\":1},{\"id\":2},{\"id\":3}]}"; // 此时可以正常调用convertToGenericDataRecord GenericData.Record record = converter.convertToGenericDataRecord(wrappedJson.getBytes(), new Schema.Parser().parse(wrappedSchemaStr));
内容的提问来源于stack exchange,提问作者luisvenezian
相关产品推荐
相关产品推荐

