Java读取含重复键JSON文件仅返回最后值,求获取全部对象的代码
问题分析
你提供的JSON格式不合法——JSON对象中不允许存在重复键(这里statements重复出现),标准JSON解析器默认只会保留最后一个重复键的对应值,这就是你只能读到最后一组数据的原因。
解决方案
方案1:修复JSON为合法格式(推荐)
先把JSON调整为标准结构,将多个statements数组合并成一个:
{ "statements": [ { "kpCustomLevel": { "region": "KNW", "statementType": "Medical", "coverageType": "DHMO" } }, { "kpCustomLevel": { "region": "KNP", "statementType": "Medical1", "coverageType": "DHMN" } } ] }
之后用Jackson或Gson等主流JSON库解析成Java对象数组即可。
步骤1:定义对应Java实体类
// KpCustomLevel.java public class KpCustomLevel { private String region; private String statementType; private String coverageType; // 无参构造、全参构造 public KpCustomLevel() {} public KpCustomLevel(String region, String statementType, String coverageType) { this.region = region; this.statementType = statementType; this.coverageType = coverageType; } // getter和setter方法 public String getRegion() { return region; } public void setRegion(String region) { this.region = region; } public String getStatementType() { return statementType; } public void setStatementType(String statementType) { this.statementType = statementType; } public String getCoverageType() { return coverageType; } public void setCoverageType(String coverageType) { this.coverageType = coverageType; } }
// Statement.java public class Statement { private KpCustomLevel kpCustomLevel; public Statement() {} public Statement(KpCustomLevel kpCustomLevel) { this.kpCustomLevel = kpCustomLevel; } public KpCustomLevel getKpCustomLevel() { return kpCustomLevel; } public void setKpCustomLevel(KpCustomLevel kpCustomLevel) { this.kpCustomLevel = kpCustomLevel; } }
// StatementsWrapper.java public class StatementsWrapper { private List<Statement> statements; public StatementsWrapper() {} public StatementsWrapper(List<Statement> statements) { this.statements = statements; } public List<Statement> getStatements() { return statements; } public void setStatements(List<Statement> statements) { this.statements = statements; } }
步骤2:用Jackson解析到数组
先添加Jackson依赖(Maven示例):
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> <!-- 使用最新稳定版即可 --> </dependency>
解析代码:
import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.IOException; import java.util.List; public class JsonParser { public static void main(String[] args) { ObjectMapper objectMapper = new ObjectMapper(); try { // 读取JSON文件并映射到Wrapper类 StatementsWrapper wrapper = objectMapper.readValue(new File("your-json-file.json"), StatementsWrapper.class); // 将List转为数组 Statement[] statementsArray = wrapper.getStatements().toArray(new Statement[0]); // 测试输出验证结果 for (Statement stmt : statementsArray) { KpCustomLevel level = stmt.getKpCustomLevel(); System.out.printf("Region: %s, StatementType: %s, CoverageType: %s%n", level.getRegion(), level.getStatementType(), level.getCoverageType()); } } catch (IOException e) { e.printStackTrace(); } } }
方案2:无法修改原始JSON时的兼容处理
如果没办法调整原始非法JSON,可以用Jackson自定义反序列化逻辑处理重复键:
自定义重复键反序列化器
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class DuplicateKeyDeserializer extends JsonDeserializer<List<Statement>> { @Override public List<Statement> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { List<Statement> statements = new ArrayList<>(); ObjectMapper mapper = (ObjectMapper) p.getCodec(); while (p.nextToken() != JsonToken.END_OBJECT) { String fieldName = p.getCurrentName(); if ("statements".equals(fieldName)) { p.nextToken(); // 读取当前statements数组并合并到总列表 List<Statement> currentBatch = mapper.readValue(p, List.class); statements.addAll(currentBatch); } else { // 跳过无关字段 p.skipChildren(); } } return statements; } }
解析实现代码
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import java.io.File; import java.io.IOException; import java.util.List; public class DuplicateKeyJsonParser { public static void main(String[] args) { ObjectMapper objectMapper = new ObjectMapper(); // 允许单个值被解析为数组(兼容数组只有一个元素的情况) objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); // 注册自定义反序列化器 SimpleModule module = new SimpleModule(); module.addDeserializer(List.class, new DuplicateKeyDeserializer()); objectMapper.registerModule(module); try { // 直接读取非法JSON并解析为Statement列表 List<Statement> statementsList = objectMapper.readValue(new File("invalid-json-file.json"), List.class); // 转为数组 Statement[] statementsArray = statementsList.toArray(new Statement[0]); // 测试输出 for (Statement stmt : statementsArray) { KpCustomLevel level = stmt.getKpCustomLevel(); System.out.printf("Region: %s, StatementType: %s, CoverageType: %s%n", level.getRegion(), level.getStatementType(), level.getCoverageType()); } } catch (IOException e) { e.printStackTrace(); } } }
注意事项
- 优先选择方案1,非法JSON在不同解析器下的行为存在差异,兼容性无法保障。
- 若使用Gson库,逻辑类似:合法JSON直接映射实体类;非法JSON需自定义
TypeAdapter处理重复键。
内容的提问来源于stack exchange,提问作者Neeraj
相关产品推荐
相关产品推荐

