迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 >

Gson Builder — 基础和命名策略

作者:迹忆客 最近更新:2022/06/08 浏览次数:

在本系列之前的博客文章中,我们已经学习了如何使用 Gson 将 Java 对象转换为 JSON,反之亦然。 到目前为止,我们已经介绍了如何设置模型以及为了获得正确的映射而重要的是什么。 通过这篇文章,我们将开始本系列的一个新的篇章,它将使用 GsonBuilder 来自定义 Gson 的行为。

GsonBuilder 基础

在我们之前发布的所有文章中,我们可以通过 Gson gson = new Gson(); 获取 Gson 的实例。 当我们需要具有标准配置的 Gson 时,这是完全有效的。 但是,Gson 有很多可以更改的小设置。 如果我们需要以稍微不标准的方式使用 Gson,这将非常方便。 为了更改某些设置,我们可以使用 GsonBuilder 使用我们的自定义配置创建一个新的 Gson 实例。

// 之前使用 Gson
Gson gson = new Gson();

// 现在使用 GsonBuilder
GsonBuilder gsonBuilder = new GsonBuilder();  
Gson gson = gsonBuilder.create();  

GsonBuilder 类提供了一个返回 Gson 实例的 .create() 方法。 使用 Gson 实例,我们可以完成我们之前展示的所有操作:将各种数据转换到 JSON,或将 JSON 转换成相应的数据。


GsonBuilder 命名策略

我们要展示的第一个 GsonBuilder 选项是命名策略。 我们一直假设 Java 模型文件和 API 请求和响应的 JSON 有效负载应用相同的命名模式。 我们已经向大家展示了如何使用 @SerializedName 来更改单个模型属性的序列化。 但是,如果 API 和 Java 模型在命名上不一致,那么使用 @SerializedName 注解更改数百个属性名称可能会很乏味。

因此,Gson 提供了配置和自定义的 FieldNamingPolicys。 出于演示目的,我们调整了 UserSimple 模型并为属性赋予了一些新名称:

public class UserNaming {  
    String Name;
    String email_of_developer;
    boolean isDeveloper;
    int _ageOfDeveloper;
}

如大家所见,我们在一个模型中统一了所有类型的命名标准。 这将产生一些看起来很有趣的 JSON,但更容易看到各种命名策略将如何影响它们。 我们可以在 GsonBuilder 上设置策略:

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY);  
Gson gson = gsonBuilder.create();  

使用上述 Gson 实例的所有转换现在都将应用字段命名策略 FieldNamingPolicy.IDENTITY。 在接下来的几节中,我们将探讨这究竟意味着什么以及预定义字段命名策略的行为方式。 让我们从最简单的开始:IDENTITY


FieldNamingPolicy IDENTITY

字段命名策略 IDENTITY 在序列化对象时使用与 Java 模型完全相同的命名。 无论我们设置 Java 模型的命名标准是什么,JSON 都将使用相同的命名标准。 上面我们奇怪命名的模型将产生以下 JSON:

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY);  
Gson gson = gsonBuilder.create();

UserNaming user = new UserNaming("jiyik", "jiyik_onmpw@163.com", true, 26);  
String usersJson = gson.toJson(user);  

usersJson 将包含:

{
  "Name": "jiyik",
  "_ageOfDeveloper": 26,
  "email_of_developer": "jiyik_onmpw@163.com",
  "isDeveloper": true
}

如大家所见,没有任何字段名称发生变化。 它从模型中复制了确切的名称。 如果我们没有设置策略或不使用 GsonBuilder 并使用 new Gson() 直接实例化 Gson,它将使用此策略。


FieldNamingPolicy LOWER_CASE_WITH_UNDERSCORES

我们要展示的第二个策略是 LOWER_CASE_WITH_UNDERSCORES。 命名很清楚,但让我们在示例模型上使用它:

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);  
Gson gson = gsonBuilder.create();

UserNaming user = new UserNaming("jiyik", "jiyik_onmpw@163.com", true, 26);  
String usersJson = gson.toJson(user);  

LOWER_CASE_WITH_UNDERSCORES 将根据大写字符拆分属性名称,并将这些大写字符替换为以 _ 开头的小写字符。 对于我们的模型,两个属性受到影响:

{
  "name": "jiyik",
  "_age_of_developer": 26,
  "email_of_developer": "jiyik_onmpw@163.com",
  "is_developer": true
}

isDeveloper_ageOfDeveloper_ 分开了。 请注意,_ageOfDeveloper 的前缀 _ 仍然存在! 如果我们不想使用下划线而是更喜欢破折号,那么下一部分可能适合大家。


FieldNamingPolicy LOWER_CASE_WITH_DASHES

我们想展示的第三个选项是 LOWER_CASE_WITH_DASHES。 它使用与之前的 LOWER_CASE_WITH_UNDERSCORES 相同的系统,但将字段名称分隔替换为 -。 让我们应用以下代码:

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES);  
Gson gson = gsonBuilder.create();

UserNaming user = new UserNaming("jiyik", "jiyik_onmpw@163.com", true, 26);  
String usersJson = gson.toJson(user);  

这将产生一个包含以下内容的 usersJson

{
  "name": "jiyik",
  "_age-of-developer": 26,
  "email_of_developer": "jiyik_onmpw@163.com",
  "is-developer": true
}

请注意它仍然只更改了两个带有大写字母的属性。 _ageOfDeveloper 的前缀下划线或 email_of_developer 的下划线不受影响! 如果我们需要更严格的策略,可以实现自己的逻辑,我们将很快向大家展示。 但在转向自定义策略之前,是时候使用最后两个预定义策略了。


FieldNamingPolicy UPPER_CAMEL_CASE

第四个策略是 UPPER_CAMEL_CASE,它使第一个字母大写。 希望我们现在知道如何使用 GsonBuilder 应用命名策略:

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE);  
Gson gson = gsonBuilder.create();

UserNaming user = new UserNaming("jiyik", "jiyik_onmpw@163.com", true, 26);  
String usersJson = gson.toJson(user);  

结果 usersJson 将是:

{
  "Name": "jiyik",
  "_AgeOfDeveloper": 26,
  "Email_of_developer": "jiyik_onmpw@163.com",
  "IsDeveloper": true
}

我们可以看到这是影响所有四个属性的第一个策略。 它会将它们全部更改为以大写字母开头,即使属性名称以前缀 _ 开头。 但是,此策略不会改变分离。 它留下相同的下划线。 下一个稍微改变了单词分隔


FieldNamingPolicy UPPER_CAMEL_CASE_WITH_SPACES

最后一个策略 UPPER_CAMEL_CASE_WITH_SPACES 几乎与 UPPER_CAMEL_CASE 相同。 无论如何,代码几乎相同:

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES);  
Gson gson = gsonBuilder.create();

UserNaming user = new UserNaming("jiyik", "jiyik_onmpw@163.com", true, 26);  
String usersJson = gson.toJson(user);  

让我们看看生成的 usersJson

{
  "Name": "jiyik",
  "_Age Of Developer": 26,
  "Email_of_developer": "jiyik_onmpw@163.com",
  "Is Developer": true
}

如大家所见,与 UPPER_CAMEL_CASE 相比没有太大变化。 唯一的区别是这两个已经有大写字母的字段在单词之间接收空格。


与 @SerializedName 交互

我们可能想知道策略如何与 @SerializedName 交互。 我们已经在之前的博客文章中演示了 @SerializedName 的用法。 让我们改变我们的 UserNaming 模型来使用@SerializedName

public class UserNaming {  
    String Name;

    @SerializedName("emailOfDeveloper")
    String email_of_developer;

    boolean isDeveloper;
    int _ageOfDeveloper;
}

当我们现在应用命名策略时会发生什么? 答案是它不会改变 @SerializedName 的属性。 例如,如果我们使用 UPPER_CAMEL_CASE,它将产生以下 JSON:

{
  "Name": "jiyik",
  "_AgeOfDeveloper": 26,
  "emailOfDeveloper": "jiyik_onmpw@163.com",
  "IsDeveloper": true
}

emailOfDeveloper@SerializedName 注解中的完全相同,并且没有获得前缀大写字母。


自定义字段命名

提供的策略与 @SerializedName 结合可能不足以涵盖我们用例。 我们可以实现自己的 FieldNamingPolicy 版本。 由于我们只能将预定义的枚举值传递给 .setFieldNamingPolicy() 方法,因此 Gson 提供了第二种方法 .setFieldNamingStrategy()

我们可以将 FieldNamingStrategy 的实例传递给适当的方法。 FieldNamingStrategy 类只有一个方法。 例如,如果我们想删除所有预定义策略都没有的下划线,我们可以使用以下代码片段:

FieldNamingStrategy customPolicy = new FieldNamingStrategy() {  
    @Override
    public String translateName(Field f) {
        return f.getName().replace("_", "");
    }
};

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.setFieldNamingStrategy(customPolicy);  
Gson gson = gsonBuilder.create();

UserNaming user = new UserNaming("jiyik", "jiyik_onmpw@163.com", true, 26);  
String usersJson = gson.toJson(user); 

生成的 JSON 将不再包含任何下划线:

{
  "Name": "jiyik",
  "ageOfDeveloper": 26,
  "emailOfDeveloper": "jiyik_onmpw@163.com",
  "isDeveloper": true
}

Gson 只接受一种策略。 因此,我们必须在单个 FieldNamingStrategy 实现中实现自己的逻辑。 如果不止一次调用我们在上面展示的方法之一,它将替换前一个。


反序列化

在这篇文章中,我们只研究了事物的序列化方面。 换句话说,在我们使用 Gson 从 Java 对象转换数据之后,JSON 是什么样子的。 所有这些命名策略在反序列化期间都具有相同的效果。 基本上,如果我们有一个 API 以小写形式返回所有值,并用下划线作为单词之间的分隔符,我们可以使用 LOWER_CASE_WITH_UNDERSCORES 作为策略并在模型中使用常规 Java 命名约定。

举个简单的例子,如果你有以下 JSON:

{
  "reviewer_name": "Jiyik"
}

我们可以拥有以下模型:

public class PostReviewer {  
    String reviewerName;
}

如果我们应用正确的命名策略,即使名称不同,Gson 也会进行映射。


总结

在本篇文章中,我们已经了解了使用 GsonBuilder 的基础知识。 我们查看了自定义 Gson 行为的第一个选项。 特别是,我们向大家展示了在 Java 对象的(反)序列化期间自定义属性命名的各种策略。

我们后面会继续介绍更多 GsonBuilder 功能。 具体来说,我们将介绍一种强制 Gson 序列化空值的方法。

除非注明转载,本站文章均为原创或翻译,欢迎转载,转载请以链接形式注明出处

本文地址:

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

热门文章

教程更新

热门标签

扫码一下
查看教程更方便