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

使用Gson序列化javafx.Color报错及opens语句警告问题求助

解决Gson序列化JavaFX Color对象的问题

问题根源

Gson默认通过反射访问对象私有字段,但JavaFX的javafx.scene.paint.Color类属于模块化封装的javafx.graphics模块,不允许外部模块(如com.google.gson)直接访问其私有字段。而你添加opens javafx.scene.paint to com.google.gson;后出现警告,是因为模块描述文件中未先声明对javafx.graphics的依赖。

推荐解决方案:自定义TypeAdapter(无需修改模块权限)

通过为Color类编写自定义序列化/反序列化适配器,绕开反射访问私有字段的限制,同时符合Java模块化设计原则。

1. 编写ColorTypeAdapter

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import javafx.scene.paint.Color;
import java.io.IOException;

public class ColorTypeAdapter extends TypeAdapter<Color> {
    @Override
    public void write(JsonWriter out, Color value) throws IOException {
        // 将Color序列化为易读的RGB+透明度JSON对象
        out.beginObject();
        out.name("red").value(value.getRed());
        out.name("green").value(value.getGreen());
        out.name("blue").value(value.getBlue());
        out.name("opacity").value(value.getOpacity());
        out.endObject();
    }

    @Override
    public Color read(JsonReader in) throws IOException {
        // 从JSON对象反序列化为Color实例
        in.beginObject();
        double red = 0, green = 0, blue = 0, opacity = 1;
        while (in.hasNext()) {
            switch (in.nextName()) {
                case "red": red = in.nextDouble(); break;
                case "green": green = in.nextDouble(); break;
                case "blue": blue = in.nextDouble(); break;
                case "opacity": opacity = in.nextDouble(); break;
            }
        }
        in.endObject();
        return Color.color(red, green, blue, opacity);
    }
}

2. 注册适配器并序列化列表

修改Gson初始化代码,注册自定义适配器,并使用try-with-resources确保文件流正确关闭:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Pixel> list = new ArrayList<>();
        list.add(new Pixel(1,1,Color.TRANSPARENT));
        list.add(new Pixel(1, 2, Color.BEIGE));
        list.add(new Pixel(2, 1, Color.RED));

        // 注册自定义TypeAdapter
        Gson gson = new GsonBuilder()
                .setPrettyPrinting()
                .registerTypeAdapter(Color.class, new ColorTypeAdapter())
                .create();

        // 写入JSON文件
        try (FileWriter fWriter = new FileWriter("pixel.json")) {
            gson.toJson(list, fWriter);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

备选方案:修复模块权限(打破封装)

如果坚持使用反射方式,需先在module-info.java中声明对JavaFX图形模块的依赖,再开放字段访问权限:

module your.module.name {
    requires javafx.graphics;
    opens javafx.scene.paint to com.google.gson;
    // 其他模块声明
}

此方法会打破JavaFX模块的封装性,不推荐用于生产环境。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 01:28:38