JSON数据如何优雅地转换为List集合?一篇讲透!
在当今的软件开发中,JSON(JavaScript Object Notation)已成为数据交换的事实标准,无论是调用RESTful API、读取配置文件,还是处理前后端数据交互,我们都会频繁地与JSON打交道,后端程序(如Java、Python等)通常使用强类型的集合类(如List、数组)来处理数据,将JSON字符串转换为程序中的List集合,是一项至关重要的基础技能。
本文将以最主流的编程语言之一——Java为例,详细讲解如何将JSON数据转换为List集合,并提供不同场景下的最佳实践。
准备工作:引入JSON处理库
Java标准库本身不直接支持JSON的序列化和反序列化,因此我们需要借助第三方库,目前最流行、功能最强大的库是 Jackson 和 Gson,本文将以Jackson为例进行讲解,因为它在Spring Boot等主流框架中被广泛使用。
如果你使用的是Maven项目,需要在 pom.xml 文件中添加Jackson的核心依赖:
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version> <!-- 建议使用最新稳定版 -->
</dependency>
 核心概念:ObjectMapper
Jackson库的核心是 ObjectMapper 类,它就像是JSON数据和Java对象之间的“翻译官”,负责将JSON字符串解析(反序列化)为Java对象,或将Java对象转换为JSON字符串(序列化)。
在进行转换之前,我们首先要创建一个 ObjectMapper 实例:
import com.fasterxml.jackson.databind.ObjectMapper; // 创建一个全局的ObjectMapper实例,推荐重复使用 ObjectMapper objectMapper = new ObjectMapper();
 场景一:将JSON数组字符串转为 List<Map>
这是最简单的一种情况,尤其当我们不确定JSON内部结构,或者只是想动态处理键值对时。List<Map> 可以非常灵活地容纳任何JSON数组数据。
假设我们有以下JSON字符串:
[
  { "id": 1, "name": "Alice", "city": "New York" },
  { "id": 2, "name": "Bob", "city": "London" },
  { "id": 3, "name": "Charlie", "city": "Paris" }
]
转换代码:
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import java.util.Map;
public class JsonToListExample {
    public static void main(String[] args) throws Exception {
        String jsonArrayString = "[\n" +
                "  { \"id\": 1, \"name\": \"Alice\", \"city\": \"New York\" },\n" +
                "  { \"id\": 2, \"name\": \"Bob\", \"city\": \"London\" },\n" +
                "  { \"id\": 3, \"name\": \"Charlie\", \"city\": \"Paris\" }\n" +
                "]";
        ObjectMapper objectMapper = new ObjectMapper();
        // 关键点:使用 TypeReference 来明确告知 ObjectMapper 我们要转换的目标类型是 List<Map>
        List<Map<String, Object>> list = objectMapper.readValue(jsonArrayString, new TypeReference<List<Map<String, Object>>>() {});
        // 打印结果
        for (Map<String, Object> map : list) {
            System.out.println(map);
        }
    }
}
代码解析:
objectMapper.readValue() 方法有两个参数:
- 源数据:可以是JSON字符串、字节数组或文件。
 - 目标类型:这里我们没有直接写 
List.class,因为Java的泛型在编译时会擦除,List.class对JVM来说只是List,它不知道List里装的是什么类型。 
为了解决这个问题,Jackson提供了 TypeReference,通过匿名内部类的方式,我们精确地告诉JVM:“我要的是一个 List<Map<String, Object>> 类型”,这样Jackson就能正确地进行转换了。
场景二:将JSON数组字符串转为自定义对象List(推荐做法)
在实际开发中,我们通常更希望将数据绑定到有明确结构的自定义Java对象(POJO/Model)中,这样可以利用编译器的类型检查,使代码更健壮、更易于维护。
创建对应的Java类(POJO)
// User.java
public class User {
    private int id;
    private String name;
    private String city;
    // 必须有无参构造函数
    public User() {
    }
    // 推荐:使用getter和setter方法
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getCity() { return city; }
    public void setCity(String city) { this.city = city; }
    // 可选:重写 toString() 方法,方便打印和调试
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}
进行转换
我们可以将JSON数组直接转换为 List<User>。
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
public class JsonToUserListExample {
    public static void main(String[] args) throws Exception {
        String jsonArrayString = "[\n" +
                "  { \"id\": 1, \"name\": \"Alice\", \"city\": \"New York\" },\n" +
                "  { \"id\": 2, \"name\": \"Bob\", \"city\": \"London\" },\n" +
                "  { \"id\": 3, \"name\": \"Charlie\", \"city\": \"Paris\" }\n" +
                "]";
        ObjectMapper objectMapper = new ObjectMapper();
        // 使用 TypeReference 来指定泛型类型 List<User>
        List<User> userList = objectMapper.readValue(jsonArrayString, new TypeReference<List<User>>() {});
        // 打印结果
        userList.forEach(System.out::println);
    }
}
代码解析:
转换逻辑与 List<Map> 类似,只是我们将 TypeReference 中的类型换成了 List<User>,Jackson会自动遍历JSON数组,将每个对象映射为 User 类的实例,并填充到 List<User> 中。
注意:
- JSON的键名必须与Java类的属性名(或通过注解映射的名称)完全匹配(或配置为不区分大小写)。
 - Java类必须有无参构造函数。
 - 属性必须有对应的 
getter和setter方法。 
场景三:处理嵌套的JSON结构
JSON结构往往很复杂,可能包含嵌套的对象或数组。
[
  {
    "id": 1,
    "name": "Alice",
    "contact": {
      "email": "alice@example.com",
      "phone": "123-456-7890"
    },
    "tags": ["developer", "java"]
  }
]
在这种情况下,我们需要为嵌套的结构也创建对应的Java类。
创建嵌套的Java类
// Contact.java
public class Contact {
    private String email;
    private String phone;
    // getters, setters, toString()...
}
// UserWithNested.java
public class UserWithNested {
    private int id;
    private String name;
    private Contact contact; // 嵌套对象
    private List<String> tags; // 嵌套数组
    // getters, setters, toString()...
}
进行转换
转换过程与之前完全相同,ObjectMapper 会自动处理这种嵌套关系。
List<UserWithNested> users = objectMapper.readValue(complexJsonString, new TypeReference<List<UserWithNested>>() {});
常见问题与解决方案
- 
问题:
UnrecognizedPropertyException- 原因:JSON中有某个属性,但在Java类中没有对应的字段。
 - 解决:在POJO类上添加注解 
@JsonIgnoreProperties(ignoreUnknown = true),告诉Jackson忽略未识别的属性。 
@JsonIgnoreProperties(ignoreUnknown = true) public class User { // ... } - 
问题:
InvalidDefinitionException(no Creators, like default constructor, exist)- 原因:Java类缺少无参构造函数。
 - 解决:为POJO类添加一个公共的无参构造函数。
 
 - 
问题:
JsonMappingException- 原因:数据类型不匹配,例如JSON中的字符串 "123" 无法转换为Java的 
int类型。 - 解决:检查JSON数据类型和Java属性类型是否一致,或者使用
 
 - 原因:数据类型不匹配,例如JSON中的字符串 "123" 无法转换为Java的 
 



		
		
		
		
还没有评论,来说两句吧...