You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中JSON转Parquet抛出InvalidSchemaException异常求助

解决Parquet写入时的InvalidSchemaException(空group错误)

这个问题我之前也碰到过,核心原因是Parquet需要明确的、非空的Schema结构,但你用List<Map<String, Object>>作为字段类型时,ReflectData无法推断出Map里具体的字段和类型,最终生成了空的group,触发了异常。

解决方案:用具体实体类替代Map

最可靠的方式是创建一个对应JSON对象的实体类,让ReflectData能正确生成包含所有字段的Schema。

1. 创建对应JSON元素的实体类

新建DataPoint类,对应你JSON数组里的每个对象:

public class DataPoint {
    private double mainBearingX;
    private double gearBoxZ;
    private long _t;
    private double mainBearingZ;
    private double gearBoxX;
    private double mainBearingY;
    private double gearBoxY;
    private double generatorX;
    private double generatorY;
    private String ts_id;

    // 必须添加getter方法,ReflectData依赖getter识别字段
    public double getMainBearingX() { return mainBearingX; }
    public double getGearBoxZ() { return gearBoxZ; }
    public long get_t() { return _t; }
    public double getMainBearingZ() { return mainBearingZ; }
    public double getGearBoxX() { return gearBoxX; }
    public double getMainBearingY() { return mainBearingY; }
    public double getGearBoxY() { return gearBoxY; }
    public double getGeneratorX() { return generatorX; }
    public double getGeneratorY() { return generatorY; }
    public String getTs_id() { return ts_id; }

    // 可选:添加setter方便赋值
    public void setMainBearingX(double mainBearingX) { this.mainBearingX = mainBearingX; }
    public void setGearBoxZ(double gearBoxZ) { this.gearBoxZ = gearBoxZ; }
    public void set_t(long _t) { this._t = _t; }
    public void setMainBearingZ(double mainBearingZ) { this.mainBearingZ = mainBearingZ; }
    public void setGearBoxX(double gearBoxX) { this.gearBoxX = gearBoxX; }
    public void setMainBearingY(double mainBearingY) { this.mainBearingY = mainBearingY; }
    public void setGearBoxY(double gearBoxY) { this.gearBoxY = gearBoxY; }
    public void setGeneratorX(double generatorX) { this.generatorX = generatorX; }
    public void setGeneratorY(double generatorY) { this.generatorY = generatorY; }
    public void setTs_id(String ts_id) { this.ts_id = ts_id; }
}

2. 修改OutPut类的字段类型

把原来的List<Map<String, Object>>换成List<DataPoint>:

public class OutPut {
    private List<DataPoint> list;

    // 添加getter和setter
    public List<DataPoint> getList() { return list; }
    public void setList(List<DataPoint> list) { this.list = list; }
}

3. 完善转换代码(别忘了写入数据)

你原来的代码只创建了Writer,但没有实际写入数据,这里补充上writer.write(output):

public static void toConvert(OutPut output) { 
    String inputFile = "test.parquetFile"; 
    Path dataFile = new Path(inputFile); 
    Schema schema = ReflectData.AllowNull.get().getSchema(OutPut.class); 
    try (ParquetWriter<OutPut> writer = AvroParquetWriter.<OutPut>builder(dataFile) 
            .withSchema(schema) 
            .withDataModel(ReflectData.get()) 
            .withConf(new Configuration()) 
            .withCompressionCodec(CompressionCodecName.SNAPPY) 
            .withWriteMode(Mode.OVERWRITE) 
            .build()) {
        // 关键:将你的数据对象写入Parquet文件
        writer.write(output);
    } catch (IOException e) { 
        e.printStackTrace(); 
    } 
}

为什么这样能解决问题?

Parquet是强Schema的列式存储格式,必须提前明确每个字段的名称、类型等信息。Map<String, Object>是动态结构,ReflectData无法确定里面有哪些字段、每个字段是什么类型,所以生成了空的group结构,而Parquet禁止写入空group的Schema。用具体实体类后,ReflectData可以通过类的getter方法自动生成完整合法的Schema,Writer就能正常工作了。

如果你的JSON字段是动态不固定的,可以考虑用Avro的GenericRecord手动构建Schema,但静态实体类是字段固定场景下最简单可靠的方案。

内容的提问来源于stack exchange,提问作者raj03

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:58:27