Gson读取resources下JSON转Java对象列表报MalformedJsonException
问题产生原因
- 核心触发
MalformedJsonException: Expected value at line 1 column 1 path $的原因:文件读取路径错误。使用Paths.get("test.json")读取文件时,默认从程序启动的工作目录查找文件,不会定位到resources资源目录下的文件,实际没有读到有效JSON内容,GSON解析空输入时直接抛出该异常。 - 存在二级逻辑错误:JSON结构和反序列化目标类型不匹配。test.json最外层数组的每个元素是包含
code、items字段的包装对象,不是直接的Item实例,就算正确读到文件,直接反序列化为List<Item>也会出现字段映射失败的问题。 - 额外注意:JSON示例中的
...是内容省略标记,如果实际test.json文件中保留了该符号,属于非法JSON语法,也会触发解析异常。
修复方案
- 修正文件读取逻辑,通过类加载器读取resources目录下的资源文件,同时使用try-with-resources语法自动关闭流避免资源泄漏:
import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.StandardCharsets; import java.util.Objects; // 注意test.json需要放在resources目录根路径下 try (Reader reader = new InputStreamReader( Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream("test.json")), StandardCharsets.UTF_8 )) { // 后续反序列化逻辑写在try块内 }
如果是静态方法里读取,把getClass()替换成对应类的class对象,比如YourClassName.class。
- 修正实体类映射关系,匹配JSON结构:
首先定义和外层数组元素对应的实体类:
import java.util.List; public class ItemGroup { private String code; private List<Item> items; // 自行补全getter、setter、toString方法 public String getCode() {return code;} public void setCode(String code) {this.code = code;} public List<Item> getItems() {return items;} public void setItems(List<Item> items) {this.items = items;} }
然后修正反序列化的类型声明,和JSON外层结构对应:
Gson gson = new Gson(); List<ItemGroup> groups = gson.fromJson(reader, new TypeToken<List<ItemGroup>>() {}.getType());
如果你最终需要拿到所有嵌套的Item对象,对结果做平铺处理即可:
List<Item> allItems = groups.stream() .flatMap(group -> group.getItems().stream()) .toList(); allItems.forEach(System.out::println);
- 检查JSON文件合法性:
- 删除文件中所有示例用的
...占位符,保证JSON语法符合规范 - 把文件编码转为无BOM头的UTF-8格式,避免文件开头的BOM特殊字符被识别为非法JSON内容
- 删除文件中所有示例用的
内容的提问来源于stack exchange,提问作者Guilherme Gonzalez
相关产品推荐
相关产品推荐

