如何从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
相关产品推荐
相关产品推荐

