1. 将 JSON 映射为简单 Java 对象
我们先从最基础的开始:将一个简单的 JSON 字符串转换为一个 Java 对象,比如 Foo
类:
public class Foo {
public int intValue;
public String stringValue;
// + 标准的 equals 和 hashCode 实现
}
对应的反序列化操作如下:
@Test
public void whenDeserializingToSimpleObject_thenCorrect() {
String json = "{\"intValue\":1,\"stringValue\":\"one\"}";
Foo targetObject = new Gson().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "one");
}
✅ 小结:Gson 默认使用字段名匹配来映射 JSON 和 Java 对象,非常直观。
2. 反序列化泛型对象
如果我们的类是泛型的,比如:
public class GenericFoo<T> {
public T theValue;
}
这时候就不能直接用 .class
来指定类型了,需要借助 TypeToken
:
@Test
public void whenDeserializingToGenericObject_thenCorrect() {
Type typeToken = new TypeToken<GenericFoo<Integer>>() { }.getType();
String json = "{\"theValue\":1}";
GenericFoo<Integer> targetObject = new Gson().fromJson(json, typeToken);
assertEquals(targetObject.theValue, new Integer(1));
}
⚠️ 踩坑提醒:泛型擦除导致 Gson 无法自动推断类型,必须显式提供 Type
。
3. 处理包含未知字段的 JSON 数据
如果 JSON 中有我们 Java 类中没有定义的字段,Gson 会怎么处理?
@Test
public void givenJsonHasExtraValues_whenDeserializing_thenCorrect() {
String json =
"{\"intValue\":1,\"stringValue\":\"one\",\"extraString\":\"two\",\"extraFloat\":2.2}";
Foo targetObject = new Gson().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "one");
}
✅ 结论:Gson 会自动忽略未知字段,不会报错。这在处理第三方 API 返回的数据时非常有用。
4. 字段名不一致的 JSON 映射
有时候 JSON 的字段名和 Java 类中的字段名不一致,比如:
@Test
public void givenJsonHasNonMatchingFields_whenDeserializingWithCustomDeserializer_thenCorrect() {
String json = "{\"valueInt\":7,\"valueString\":\"seven\"}";
GsonBuilder gsonBldr = new GsonBuilder();
gsonBldr.registerTypeAdapter(Foo.class, new FooDeserializerFromJsonWithDifferentFields());
Foo targetObject = gsonBldr.create().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 7);
assertEquals(targetObject.stringValue, "seven");
}
这时我们需要自定义一个反序列化器:
public class FooDeserializerFromJsonWithDifferentFields implements JsonDeserializer<Foo> {
@Override
public Foo deserialize
(JsonElement jElement, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
JsonObject jObject = jElement.getAsJsonObject();
int intValue = jObject.get("valueInt").getAsInt();
String stringValue = jObject.get("valueString").getAsString();
return new Foo(intValue, stringValue);
}
}
⚠️ 提示:这种方式适合处理字段名不一致但结构清晰的场景。
5. 将 JSON 数组转换为 Java 数组
JSON 数组也可以轻松转换为 Java 数组:
@Test
public void givenJsonArrayOfFoos_whenDeserializingToArray_thenCorrect() {
String json = "[{\"intValue\":1,\"stringValue\":\"one\"}," +
"{\"intValue\":2,\"stringValue\":\"two\"}]";
Foo[] targetArray = new GsonBuilder().create().fromJson(json, Foo[].class);
assertThat(Lists.newArrayList(targetArray), hasItem(new Foo(1, "one")));
assertThat(Lists.newArrayList(targetArray), hasItem(new Foo(2, "two")));
assertThat(Lists.newArrayList(targetArray), not(hasItem(new Foo(1, "two"))));
}
✅ 技巧:使用 Foo[].class
指定目标类型即可。
6. 将 JSON 数组转换为 Java 集合
如果你更喜欢用集合而不是数组,Gson 也支持:
@Test
public void givenJsonArrayOfFoos_whenDeserializingCollection_thenCorrect() {
String json =
"[{\"intValue\":1,\"stringValue\":\"one\"},{\"intValue\":2,\"stringValue\":\"two\"}]";
Type targetClassType = new TypeToken<ArrayList<Foo>>() { }.getType();
Collection<Foo> targetCollection = new Gson().fromJson(json, targetClassType);
assertThat(targetCollection, instanceOf(ArrayList.class));
}
⚠️ 注意:这里必须通过 TypeToken
获取泛型类型。
7. 嵌套对象的反序列化
如果对象中包含嵌套对象,比如:
public class FooWithInner {
public int intValue;
public String stringValue;
public InnerFoo innerFoo;
public class InnerFoo {
public String name;
}
}
反序列化代码如下:
@Test
public void whenDeserializingToNestedObjects_thenCorrect() {
String json = "{\"intValue\":1,\"stringValue\":\"one\",\"innerFoo\":{\"name\":\"inner\"}}";
FooWithInner targetObject = new Gson().fromJson(json, FooWithInner.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "one");
assertEquals(targetObject.innerFoo.name, "inner");
}
✅ 结论:Gson 支持自动递归解析嵌套对象,无需额外配置。
8. 使用自定义构造器进行反序列化
默认情况下,Gson 会使用无参构造器创建对象。但如果你希望使用带参构造器,可以使用 InstanceCreator
:
public class FooInstanceCreator implements InstanceCreator<Foo> {
@Override
public Foo createInstance(Type type) {
return new Foo("sample");
}
}
注册并使用:
@Test
public void whenDeserializingUsingInstanceCreator_thenCorrect() {
String json = "{\"intValue\":1}";
GsonBuilder gsonBldr = new GsonBuilder();
gsonBldr.registerTypeAdapter(Foo.class, new FooInstanceCreator());
Foo targetObject = gsonBldr.create().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "sample");
}
构造器如下:
public Foo(String stringValue) {
this.stringValue = stringValue;
}
⚠️ 适用场景:当你需要初始化某些字段为默认值,或依赖注入时很有用。
9. 总结
本文通过多个常见场景,展示了如何使用 Gson 高效地将 JSON 映射为 Java 对象。包括:
- 简单对象
- 泛型对象
- 字段不一致处理
- 数组与集合转换
- 嵌套对象
- 自定义构造器
📌 示例代码仓库:GitHub 项目地址(基于 Eclipse,可直接导入运行)