2. 序列化对象数组
我们先从最基础的场景开始:将一个对象数组序列化为 JSON 字符串。
@Test
public void givenArrayOfObjects_whenSerializing_thenCorrect() {
SourceClass[] sourceArray = {new SourceClass(1, "one"), new SourceClass(2, "two")};
String jsonString = new Gson().toJson(sourceArray);
String expectedResult =
"[{"intValue":1,"stringValue":"one"},{"intValue":2,"stringValue":"two"}]";
assertEquals(expectedResult, jsonString);
}
✅ 简单粗暴,Gson 直接搞定,无需额外配置。
3. 序列化集合类型
和数组类似,Gson 也能直接处理 Java 集合:
@Test
public void givenCollection_whenSerializing_thenCorrect() {
Collection<SourceClass> sourceCollection =
Lists.newArrayList(new SourceClass(1, "one"), new SourceClass(2, "two"));
String jsonCollection = new Gson().toJson(sourceCollection);
String expectedResult =
"[{"intValue":1,"stringValue":"one"},{"intValue":2,"stringValue":"two"}]";
assertEquals(expectedResult, jsonCollection);
}
⚠️ 注意:这里用的是 Lists.newArrayList()
,属于 Guava 提供的便捷工具。
4. 自定义字段名序列化
有时我们希望输出的 JSON 字段名和 Java 对象属性名不一致,比如把 intValue
输出为 otherIntValue
。
这时候就需要自定义序列化器了:
@Test
public void givenUsingCustomSerializer_whenChangingNameOfFieldOnSerializing_thenCorrect() {
SourceClass sourceObject = new SourceClass(7, "seven");
GsonBuilder gsonBuildr = new GsonBuilder();
gsonBuildr.registerTypeAdapter(SourceClass.class, new DifferentNameSerializer());
String jsonString = gsonBuildr.create().toJson(sourceObject);
String expectedResult = "{"otherIntValue":7,"otherStringValue":"seven"}";
assertEquals(expectedResult, jsonString);
}
对应的自定义序列化器如下:
public class DifferentNameSerializer implements JsonSerializer<SourceClass> {
@Override
public JsonElement serialize
(SourceClass src, Type typeOfSrc, JsonSerializationContext context) {
String otherIntValueName = "otherIntValue";
String otherStringValueName = "otherStringValue";
JsonObject jObject = new JsonObject();
jObject.addProperty(otherIntValueName, src.getIntValue());
jObject.addProperty(otherStringValueName, src.getStringValue());
return jObject;
}
}
💡 踩坑提示:记得注册 TypeAdapter,否则自定义逻辑不会生效。
5. 忽略特定字段序列化
有些字段不想暴露给前端?可以使用自定义序列化器来忽略它们:
@Test
public void givenIgnoringAField_whenSerializingWithCustomSerializer_thenFieldIgnored() {
SourceClass sourceObject = new SourceClass(7, "seven");
GsonBuilder gsonBuildr = new GsonBuilder();
gsonBuildr.registerTypeAdapter(SourceClass.class, new IgnoringFieldsSerializer());
String jsonString = gsonBuildr.create().toJson(sourceObject);
String expectedResult = "{"intValue":7}";
assertEquals(expectedResult, jsonString);
}
自定义序列化器实现:
public class IgnoringFieldsSerializer implements JsonSerializer<SourceClass> {
@Override
public JsonElement serialize
(SourceClass src, Type typeOfSrc, JsonSerializationContext context) {
String intValue = "intValue";
JsonObject jObject = new JsonObject();
jObject.addProperty(intValue, src.getIntValue());
return jObject;
}
}
⚠️ 如果你能修改源码,推荐使用 @Expose
或 transient
关键字来控制字段是否序列化,会更简洁。
6. 条件性序列化字段
这是比较高级的用法:只有满足特定条件的字段才会被序列化。例如只序列化正整数的 intValue
:
@Test
public void givenUsingCustomDeserializer_whenFieldNotMatchesCriteria_thenIgnored() {
SourceClass sourceObject = new SourceClass(-1, "minus 1");
GsonBuilder gsonBuildr = new GsonBuilder();
gsonBuildr.registerTypeAdapter(SourceClass.class,
new IgnoringFieldsNotMatchingCriteriaSerializer());
Gson gson = gsonBuildr.create();
Type sourceObjectType = new TypeToken<SourceClass>() {}.getType();
String jsonString = gson.toJson(sourceObject, sourceObjectType);
String expectedResult = "{"stringValue":"minus 1"}";
assertEquals(expectedResult, jsonString);
}
对应的自定义序列化器如下:
public class IgnoringFieldsNotMatchingCriteriaSerializer
implements JsonSerializer<SourceClass> {
@Override
public JsonElement serialize
(SourceClass src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jObject = new JsonObject();
// Criteria: intValue >= 0
if (src.getIntValue() >= 0) {
String intValue = "intValue";
jObject.addProperty(intValue, src.getIntValue());
}
String stringValue = "stringValue";
jObject.addProperty(stringValue, src.getStringValue());
return jObject;
}
}
🎯 这种方式非常灵活,适合处理一些敏感字段或业务规则控制的输出逻辑。
📌 总结一下,以上就是 Gson 中常见的几种序列化场景。虽然 Gson 默认已经很好用了,但在一些特殊需求下(比如字段重命名、条件输出),自定义 JsonSerializer
还是非常实用的。掌握这些技巧,日常开发中基本可以应对大部分 JSON 序列化的问题了。