Gson:数据世界的翻译官
Gson就像个语言天才,能瞬间把JSON字符串变成对象(反序列化),也能把对象打包成JSON包裹(序列化)。举个栗子,当服务器扔给你这样一坨数据:
{
"name": "小明",
"age": 18,
"hobbies": ["coding", "gaming"]
}
Gson能瞬间把它变成:
Coder coder = new Gson().formJson(json, Code.class):
核心机密:TypeAdapter联盟
适配器界的变形金刚
TypeAdapter就像是不同部门的专员,每个类型都有自己的专属处理员。比如遇到Date类型,就派Date专员;遇到自定义的User类,就派反射专员。
// 以Date类型为例的简化版适配器
public class DateTypeAdapter extends TypeAdapter<Date> {
private final DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
@Override
public void write(JsonWriter out, Date value) throws IOException {
out.value(format.format(value)); // 把Date变成字符串
}
@Override
public Date read(JsonReader in) throws IOException {
try {
return format.parse(in.nextString()); // 把字符串还原成Date
} catch (ParseException e) {
throw new JsonParseException(e);
}
}
}
反射处理的黑科技
当遇到自定义类时,反射适配器就开始骚操作了:
public class ReflectiveTypeAdapter<T> extends TypeAdapter<T> {
// 构造器工厂
private final ObjectConstructor<T> constructor;
// 字段绑定表(像快递单号对照表)
private final Map<String, BoundField> boundFields;
@Override
public T read(JsonReader in) throws IOException {
T instance= constructor.construct(); // 像拆快递一样创建对象
in.beginObject();
while (in.hasNext()) {
String fieldName = in.nextName(); // 读取字段名
BoundField field = boundFields.get(fieldName);
if (field != null) {
field.read(in, instance); // 按字段赋值
} else {
in.skipValue(); // 不认识的就扔掉
}
}
in.endObject();
return instance;
}
}
工厂流水线的魔法
Gson内部有个TypeAdapter生产流水线,用工厂模式高效制造适配器:
public class Gson {
// 适配器工厂列表(生产车间集合)
private final List<TypeAdapterFactory> factories;
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
// 走流水线逐个车间问能不能生产
for (TypeAdapterFactory factory : factories) {
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
return candidate; // 找到能生产的车间
}
}
throw new IllegalArgumentException("没有适配器能处理: " + type);
}
}
自定义你的专属翻译
方案一:全能型选手(继承TypeAdapter)
适合需要精确控制序列化和反序列化的场景:
public class UserAdapter extends TypeAdapter<User> {
@Override
public void write(JsonWriter out, User user) throws IOException {
out.beginObject();
out.name("fullName").value(user.getName()); // 字段重命名
out.name("age").value(user.getAge());
out.endObject();
}
@Override
public User read(JsonReader in) throws IOException {
User user = new User();
in.beginObject();
while (in.hasNext()) {
switch (in.nextName()) {
case"fullName":
user.setName(in.nextString());
break;
case"age":
user.setAge(in.nextInt());
break;
}
}
in.endObject();
return user;
}
}
方案二:灵活派(实现接口)
适合只需要处理单方向的场景:
public class UserDeserializer implements JsonDeserializer<User> {
@Override
public User deserialize(JsonElement json, Type type,
JsonDeserializationContext context) {
JsonObject obj= json.getAsJsonObject();
User user=new User();
// 处理嵌套对象
user.setAddress(context.deserialize(obj.get("address"), Address.class));
// 转换日期格式
user.setBirthday(new Date(obj.get("birthday").getAsLong()));
return user;
}
}
开发小贴士
日期处理的坑:建议统一注册日期适配器
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.create();
忽略未知字段:避免解析报错
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
Gson像一支设计模式交响乐团:
- • 适配器模式:解决接口兼容问题
- • 工厂模式:灵活创建对象
- • 反射机制:处理未知类型
- • 建造者模式:优雅配置参数
调用gson.fromJson()时,不妨想象背后这支交响乐团正在为你演奏数据的魔法。好的库设计就像乐谱,每个模式都在恰到好处的位置奏响和谐的旋律。