Gson注解大全:@Expose、@SerializedName实战

Gson注解大全:@Expose、@SerializedName实战

【免费下载链接】gson A Java serialization/deserialization library to convert Java Objects into JSON and back 【免费下载链接】gson 项目地址: https://gitcode.com/gh_mirrors/gs/gson

Gson(Google JSON)是一个强大的Java序列化/反序列化库,能够将Java对象与JSON格式相互转换。在Gson的众多特性中,注解(Annotation)机制为开发者提供了灵活的对象序列化控制手段。本文将深入剖析Gson中最常用的两个核心注解——@Expose@SerializedName,通过源码解析、实战案例和最佳实践,帮助开发者掌握注解的高级应用技巧,解决JSON字段映射与序列化控制的常见痛点。

注解基础:Gson注解体系概述

Gson注解是Java对象与JSON转换过程中的"元数据指令",通过在类字段或方法上添加特定注解,开发者可以精确控制序列化/反序列化行为。Gson注解体系主要包含字段控制(如@Expose)、命名映射(如@SerializedName)、版本控制(@Since/@Until)和自定义适配器(@JsonAdapter)四大类。其中@Expose@SerializedName作为最基础也最常用的注解,构成了Gson对象映射的核心控制手段。

mermaid

Gson注解的实现位于gson/src/main/java/com/google/gson/annotations/目录下,所有注解均使用@Retention(RetentionPolicy.RUNTIME)保留策略,确保在运行时可通过反射机制被Gson框架识别处理。

@Expose:序列化/反序列化权限控制

@Expose注解用于标记类字段是否参与JSON序列化与反序列化过程,提供了细粒度的序列化权限控制。与Java的transient关键字不同,@Expose通过注解参数实现更灵活的序列化策略配置。

注解定义与参数解析

@Expose注解的源码定义如下(gson/src/main/java/com/google/gson/annotations/Expose.java):

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Expose {
    /**
     * 是否参与序列化,默认true
     */
    boolean serialize() default true;
    
    /**
     * 是否参与反序列化,默认true
     */
    boolean deserialize() default true;
}

该注解包含两个布尔型参数:

  • serialize:控制字段是否被序列化(Java对象→JSON)
  • deserialize:控制字段是否被反序列化(JSON→Java对象)

默认情况下,两个参数均为true,表示字段既参与序列化也参与反序列化。

启用与生效条件

重要注意@Expose注解默认不生效,必须通过GsonBuilder显式启用排除未标注@Expose的字段:

Gson gson = new GsonBuilder()
    .excludeFieldsWithoutExposeAnnotation() // 启用@Expose过滤
    .create();

未启用此配置时,Gson将忽略@Expose注解,所有字段(除transient修饰的)均参与序列化/反序列化。

使用场景与示例

基础使用示例
public class User {
    @Expose private String username;       // 参与序列化和反序列化
    @Expose(serialize = false) private String password; // 仅反序列化
    @Expose(deserialize = false) private String token;  // 仅序列化
    private String internalId;            // 未标注,启用过滤后不参与
}
测试用例分析

Gson官方测试类ExposeFieldsTestgson/src/test/java/com/google/gson/functional/ExposeFieldsTest.java)定义了如下测试模型:

private static class ExposeTestTarget {
    @Expose private final Integer a;
    @Expose(serialize = false) private final Integer b;
    @Expose(deserialize = false) private final Integer c;
    @Expose(serialize = false, deserialize = false) private final Integer d;
    private final Integer e; // 未标注@Expose
}

当启用excludeFieldsWithoutExposeAnnotation()后,不同操作的字段包含情况如下:

字段序列化(serialize)反序列化(deserialize)说明
a✅ 包含✅ 包含默认配置,双向参与
b❌ 排除✅ 包含仅反序列化
c✅ 包含❌ 排除仅序列化
d❌ 排除❌ 排除双向排除
e❌ 排除❌ 排除未标注@Expose
与transient的区别
特性@Expose注解transient关键字
控制粒度可分别控制序列化/反序列化同时控制序列化和反序列化
启用方式需要GsonBuilder配置JVM原生支持,无需额外配置
灵活性高(四个组合模式)低(仅开/关)
适用场景细粒度权限控制简单排除需求

高级用法:Java 17 Records支持

Gson对Java 17 Records的@Expose支持可参考测试类Java17RecordTestgson/src/test/java/com/google/gson/functional/Java17RecordTest.java):

record RecordWithExpose(@Expose int a, int b) {}

// 序列化结果仅包含标注@Expose的字段a

@SerializedName:JSON字段命名映射

@SerializedName注解用于指定Java字段与JSON属性之间的映射关系,解决Java命名规范(驼峰式)与JSON命名规范(下划线、短横线等)不一致的问题,同时支持多别名反序列化。

注解定义与参数解析

@SerializedName注解的源码定义如下(gson/src/main/java/com/google/gson/annotations/SerializedName.java):

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface SerializedName {
    /**
     * JSON序列化的字段名
     */
    String value();
    
    /**
     * 反序列化时的备选字段名
     */
    String[] alternate() default {};
}

包含两个参数:

  • value:必填,指定序列化时使用的JSON字段名
  • alternate:可选,指定反序列化时可接受的备选字段名数组

基础命名映射

最常见的用途是修改JSON输出的字段名:

public class User {
    @SerializedName("user_name") 
    private String userName; // Java驼峰式,JSON下划线式
}

// 序列化结果: {"user_name":"张三"}

多别名反序列化

alternate参数允许JSON使用多个字段名映射到同一个Java字段:

public class Metric {
    @SerializedName(value = "temp", alternate = {"temperature", "t"})
    private double temperature;
}

反序列化时,以下三种JSON格式均可正确映射:

{"temp": 25.5}
{"temperature": 25.5}
{"t": 25.5}

注意alternate仅影响反序列化,序列化时始终使用value指定的名称。

枚举类型的序列化控制

@SerializedName可用于修改枚举常量的JSON表示,如测试类EnumTestgson/src/test/java/com/google/gson/functional/EnumTest.java)所示:

private enum Gender {
    @SerializedName("boy") MALE,
    @SerializedName("girl") FEMALE
}

// 序列化Gender.MALE将得到"boy"

另一个测试类EnumWithObfuscatedTestgson/src/test/java/com/google/gson/functional/EnumWithObfuscatedTest.java)展示了混淆场景的应用:

enum MailType {
    @SerializedName("MAIL") MAIL_TYPE,
    @SerializedName("FEMAIL") FEMAIL_TYPE
}

特殊字符与命名策略

@SerializedName可以定义包含特殊字符的JSON字段名,如测试类NamingPolicyTestgson/src/test/java/com/google/gson/functional/NamingPolicyTest.java)中的示例:

private static class SpecialSerializedName {
    @SerializedName("@foo") String atFoo;
    @SerializedName("a") String b;
    @SerializedName("@value\"_s$\\") String specialChars;
}

序列化结果将保留这些特殊字符,不受全局命名策略影响。

实战技巧与最佳实践

组合使用策略

@Expose@SerializedName可以组合使用,实现更精确的控制:

public class Product {
    @Expose
    @SerializedName("product_id")
    private Long id;
    
    @Expose(serialize = false)
    @SerializedName(value = "price", alternate = {"cost", "value"})
    private BigDecimal price;
}

常见问题解决方案

问题1:@Expose注解不生效

排查步骤

  1. 确认是否通过GsonBuilder启用了excludeFieldsWithoutExposeAnnotation()
  2. 检查字段是否为private(Gson默认只处理private字段)
  3. 确认字段未被transient修饰(transient优先级高于@Expose
问题2:alternate别名不生效

排查步骤

  1. 确认Gson版本≥2.4(alternate参数在2.4版本引入)
  2. 检查是否将alternate用于序列化(仅反序列化有效)
  3. 确认JSON中是否同时出现多个别名(此时取第一个匹配的值)

性能考量

  • 注解处理开销:Gson在首次序列化类时缓存注解信息,后续使用无性能损耗
  • 字段过滤效率:启用excludeFieldsWithoutExposeAnnotation()后,字段过滤在反射阶段完成,建议对敏感字段优先使用transient

与其他特性的协同

与TypeAdapter的配合

自定义TypeAdapter时,@SerializedName定义的名称仍会生效,适配器将接收注解指定的JSON字段名。

与版本控制注解的协同

@SerializedName可与@Since/@Until版本注解配合使用:

public class Article {
    @Expose
    @SerializedName("title")
    @Since(1.0)
    private String title;
    
    @Expose
    @SerializedName("content")
    @Since(1.1)
    private String content;
}

通过GsonBuilder.setVersion(1.0)可控制不同版本字段的包含。

总结与扩展学习

核心知识点回顾

注解核心作用关键参数启用方式
@Expose控制序列化/反序列化权限serializedeserializeGsonBuilder.excludeFieldsWithoutExposeAnnotation()
@SerializedName定义JSON字段名映射valuealternate无需额外配置,直接生效

注解处理流程

mermaid

扩展学习资源

通过掌握@Expose@SerializedName的使用技巧,开发者可以轻松应对大多数JSON映射场景,编写更安全、更灵活的序列化代码。在实际项目中,建议结合具体业务需求制定注解使用规范,并充分利用Gson提供的测试用例验证序列化行为。

【免费下载链接】gson A Java serialization/deserialization library to convert Java Objects into JSON and back 【免费下载链接】gson 项目地址: https://gitcode.com/gh_mirrors/gs/gson

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值