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

如何从JSON文件提取name字段填充JavaFX ComboBox?

问题:无法从JSON提取所有name字段填充JavaFX ComboBox

我尝试从JSON文件中提取特定字段(name)来填充JavaFX的ComboBox,但控制台输出的Map仅显示{gene2=gene2 gcatcgtgggcgctatatcat},甚至出现空Map的情况,无法将所有基因name字段正确添加到ComboBox中。


相关代码

1. 解析JSON的ReferencesParser类

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;

public class ReferencesParser {

    private final File jsonFile;

    public ReferencesParser(File jsonFile) {
        this.jsonFile = jsonFile;
    }

    public Map<ReferencesEnum, Reference> parseReferenceFile() {

        Map<ReferencesEnum, Reference> referencesMap = new HashMap<>();

        try {
            String content = new String(Files.readAllBytes(this.jsonFile.toPath()));
            JSONObject json = new JSONObject(content);
            for (Object object : (JSONArray) json.get("genes")) {
                JSONObject geneObject = (JSONObject) object;

                Long id = geneObject.getLong("id");
                String name = geneObject.getString("name");
                String sequence = geneObject.getString("sequence");

                Reference reference = new Reference(id, name, sequence);
                referencesMap.put(ReferencesEnum.valueOf(name), reference);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return referencesMap;
    }
}

2. 数据源genes.json

{
  "genes": [
    { "id":"1","name":"gene1", "sequence": "gcattgtgggcgctatattgt" },
    { "id":"2","name":"gene2", "sequence": "gcattgtgggcgctatattcc" },
    { "id":"3","name":"gene3", "sequence": "gcatcgtgggcgctatatcat" }
  ]
}

3. FXML控制器代码片段

...
@FXML
private ComboBox<String> choosegene;

@FXML
public void initialize(){
    try {
        populateGene_reference();
        System.out.println(referencesMap);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (CompoundNotFoundException e) {
        e.printStackTrace();
    }
};

private void populateGene_reference() throws IOException, CompoundNotFoundException {
    URL url = getClass().getResource("/genes.json");
    if (url != null) {
        File geneFile = new File(url.getPath());
        ReferencesParser parser = new ReferencesParser(geneFile);
        Map<ReferencesEnum, Reference> referencesMap = parser.parseReferenceFile();
        System.out.println("refmap = " + referencesMap);
        choosegene.getItems().add(String.valueOf(referencesMap));

问题分析与修复方案

1. 核心问题1:枚举匹配失败导致解析中断

ReferencesEnum.valueOf(name)会在枚举中不存在对应name值时抛出IllegalArgumentException,而当前代码未捕获该异常,导致循环直接终止,后续基因条目无法添加到Map中。

修复:添加异常捕获,避免解析中断
修改parseReferenceFile方法,在循环内捕获枚举匹配异常,跳过无效条目并记录日志:

public Map<ReferencesEnum, Reference> parseReferenceFile() {
    Map<ReferencesEnum, Reference> referencesMap = new HashMap<>();
    try {
        String content = new String(Files.readAllBytes(this.jsonFile.toPath()));
        JSONObject json = new JSONObject(content);
        for (Object object : (JSONArray) json.get("genes")) {
            JSONObject geneObject = (JSONObject) object;
            Long id = Long.parseLong(geneObject.getString("id")); // 修复id类型问题
            String name = geneObject.getString("name");
            String sequence = geneObject.getString("sequence");
            try {
                Reference reference = new Reference(id, name, sequence);
                referencesMap.put(ReferencesEnum.valueOf(name), reference);
            } catch (IllegalArgumentException e) {
                System.err.println("基因名称" + name + "无对应枚举值,已跳过");
            }
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    return referencesMap;
}

2. 核心问题2:ComboBox填充方式错误

当前代码直接将整个Map转为字符串添加到ComboBox,导致ComboBox只有一个条目(Map的字符串表示),而非逐个添加基因name。

修复:遍历Map提取name字段填充ComboBox
修改控制器的populateGene_reference方法:

private void populateGene_reference() throws IOException, CompoundNotFoundException {
    URL url = getClass().getResource("/genes.json");
    if (url != null) {
        File geneFile = new File(url.getPath());
        ReferencesParser parser = new ReferencesParser(geneFile);
        Map<ReferencesEnum, Reference> referencesMap = parser.parseReferenceFile();
        System.out.println("refmap = " + referencesMap);
        
        // 清空原有条目并逐个添加基因name
        choosegene.getItems().clear();
        for (Reference ref : referencesMap.values()) {
            choosegene.getItems().add(ref.getName());
        }
    }
}

3. 附加问题:JSON id类型不匹配

JSON中id是字符串类型("id":"1"),但代码用getLong("id")会抛出类型转换异常,需修改为:

  • 要么将JSON中的id改为数字类型:"id":1
  • 要么在代码中先转字符串再转Long:Long id = Long.parseLong(geneObject.getString("id"));

4. 进阶优化:解决Jar包内资源读取问题

当项目打包为Jar后,getResource获取的URL无法直接转为File,建议修改ReferencesParser支持从InputStream读取:

public class ReferencesParser {
    private final InputStream inputStream;

    public ReferencesParser(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    public Map<ReferencesEnum, Reference> parseReferenceFile() {
        Map<ReferencesEnum, Reference> referencesMap = new HashMap<>();
        try {
            String content = new String(inputStream.readAllBytes());
            JSONObject json = new JSONObject(content);
            // 解析逻辑同前...
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return referencesMap;
    }
}

控制器调用改为:

private void populateGene_reference() throws IOException, CompoundNotFoundException {
    InputStream inputStream = getClass().getResourceAsStream("/genes.json");
    if (inputStream != null) {
        ReferencesParser parser = new ReferencesParser(inputStream);
        Map<ReferencesEnum, Reference> referencesMap = parser.parseReferenceFile();
        // 填充ComboBox逻辑同前...
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 15:10:23