1. 选择 JSON 库
Java 中常用的 JSON 库:
-
Jackson(推荐):高性能,功能丰富,支持注解和复杂类型。
-
Gson:Google 的库,简单易用。
-
org.json:轻量级,但功能较少。
Maven 依赖(Jackson):
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
2. 基本反序列化步骤
示例(Jackson):
import com.fasterxml.jackson.databind.ObjectMapper;
public class Person {
public String name;
public int age;
}
public class Main {
public static void main(String[] args) throws Exception {
String jsonStr = "{\"name\":\"Alice\",\"age\":30}";
ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue(jsonStr, Person.class);
System.out.println(person.name); // 输出: Alice
}
}
3. 处理字段名称不一致
使用 @JsonProperty 注解映射 JSON 字段名与类属性:
public class Person {
@JsonProperty("user_name")
public String name;
}
4. 处理日期格式
JSON 中没有日期类型,需指定格式:
public class Event {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC")
public Date eventDate;
}
5. 处理嵌套对象和数组
嵌套对象:
public class Address {
public String city;
}
public class User {
public String name;
public Address address;
}
String json = "{\"name\":\"Bob\",\"address\":{\"city\":\"Paris\"}}";
User user = mapper.readValue(json, User.class);
数组:
String jsonArray = "[{\"name\":\"Alice\"}, {\"name\":\"Bob\"}]";
Person[] people = mapper.readValue(jsonArray, Person[].class);
6. 处理多态类型(子类选择)
使用 @JsonTypeInfo 和 @JsonSubTypes 注解:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Cat.class, name = "cat"),
@JsonSubTypes.Type(value = Dog.class, name = "dog")
})
public abstract class Animal {}
public class Cat extends Animal { public boolean likesCream; }
public class Dog extends Animal { public int boneCount; }
String json = "{\"type\":\"dog\",\"boneCount\":3}";
Animal animal = mapper.readValue(json, Animal.class);
7. 处理未知字段
配置 Jackson 忽略未知字段:
ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
8. 自定义反序列化逻辑
实现 JsonDeserializer 接口:
public class CustomDeserializer extends JsonDeserializer<CustomObject> {
@Override
public CustomObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonNode node = p.getCodec().readTree(p);
String value = node.get("field").asText();
return new CustomObject(value);
}
}
// 注册自定义反序列化器
SimpleModule module = new SimpleModule();
module.addDeserializer(CustomObject.class, new CustomDeserializer());
mapper.registerModule(module);
9. 处理空值和默认值
允许字段为 null:
public class Person {
public String middleName; // 默认允许 null
}
设置默认值(使用构造函数或 Builder 模式):
public class Person {
private String name;
private int age = 18; // 默认值
@JsonCreator
public Person(@JsonProperty("name") String name, @JsonProperty("age") Integer age) {
this.name = name;
if (age != null) this.age = age;
}
}
10. 验证和调试
-
捕获异常:处理
JsonParseException和JsonMappingException。 -
日志记录:启用 Jackson 的
DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES调试。 -
单元测试:验证复杂 JSON 的解析逻辑。
常见错误排查
-
类型不匹配
JSON 中的值类型必须与 Java 类字段类型一致(如intvsString)。 -
缺少无参构造函数
如果类没有无参构造器,需使用@JsonCreator注解:public class Person { private String name; @JsonCreator public Person(@JsonProperty("name") String name) { this.name = name; } } -
循环引用
避免对象间循环依赖,或使用@JsonIgnore忽略某个字段:public class User { public String name; @JsonIgnore public User friend; // 忽略循环引用 } -
泛型类型擦除
反序列化泛型集合时,需使用TypeReference:String json = "[{\"name\":\"Alice\"}]"; List<Person> list = mapper.readValue(json, new TypeReference<List<Person>>() {});
高级技巧
-
全局配置 ObjectMapper:
配置日期格式、时区、空值处理等:ObjectMapper mapper = new ObjectMapper(); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd")); mapper.setTimeZone(TimeZone.getTimeZone("UTC")); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); -
性能优化:
复用ObjectMapper实例(线程安全),避免重复创建。 -
JSON 到 Map 的转换:
String json = "{\"key\":\"value\"}"; Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>() {});
通过以上步骤和技巧,可以高效解决 Java 中 JSON 反序列化的常见问题。
6672

被折叠的 条评论
为什么被折叠?



