我对Java中的序列化还很陌生,在阅读它的过程中,我收集到了几个问题。
假设你想对一个json响应进行格式化,这个json响应有一堆字段(例如a,b,c,d,e,f,g,h),但你只想要a,b,c。你试图访问的API是分页的,所以你循环遍历它们。你还声明了一个元数据类,比如Sample.java这样只包含你想要的字段:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Sample {
private String a;
private String b;
private String c;
}
字符串
假设你的服务类是这样做的:
UriComponentsBuilder createBranchUri = UriComponentsBuilder.fromUriString(requestUrl);
try {
Gson gson = new Gson();
Type sampleListType = new TypeToken<List<Sample>>() {}.getType();
//loop through the pages and make requests JsonArray sampleLines = paginatedRequest(restTemplate, createBranchUri, "values");
List<Sample> stashLines = gson.fromJson(sampleLines, sampleListType);
..........
型
可以吗?这意味着它将处理序列化而不会出错,并正确地为String a,B和c分配值?或者我们只能通过使用这里描述的排除策略或直接索引到json对象中来“排除”字段。换句话说-gson解析响应时的默认行为是什么(在本例中:d,e...),它在Type中找不到等价的变量?另外,顺序重要吗?假设Map的顺序是a,b,c,d....如果我们在Sample中切换a和b的位置会发生什么?
1条答案
按热度按时间lmyy7pcs1#
字符串
为了避免误解:Gson只使用无args构造函数,并使用反射设置和获取字段值,而不使用任何setter或getter方法。(唯一的例外是Java Record Classes,其中Gson确实使用args构造函数和访问器方法。)
当gson解析一个响应(在本例中:d,e...)时,它在Type中找不到等价的变量时,默认的行为是什么?
它只是忽略它们。但不幸的是,这也是你目前无法配置的,请参阅Gson issue 188。
使用排除策略“排除”字段
Gson的
ExclusionStrategy
是相反的用例:一个字段存在于你的Java类中,但你不想它被序列化或非序列化。对于简单的情况,你也可以让字段transient
排除它。另外,顺序重要吗?假设Map的顺序是a,B,c,d..
Java类中字段的顺序在从JSON序列化时并不重要,但在序列化为JSON时却很重要。
在大多数情况下,JSON数据中的顺序在格式化时并不重要,在您的用例中很可能也不重要。重要的情况是:
{"a":1,"a":2}
将具有与{"a":2}
相同的效果。Map
,Object
或JsonObject
。然后Gson将创建一个Map
示例,该示例保留了顺序,例如当您在Map.entrySet()
上并行化时可以看到。但是不同的迭代顺序可能对您的应用程序逻辑无关紧要(可能也不应该)。型
在Gson版本>= 2.10中,你可以使用
Gson.fromJson(..., TypeToken)
重载。你应该更喜欢它们而不是你正在使用的Gson.fromJson(..., Type)
重载,因为它们是类型安全的[1]。所以你可以将代码改为:型
在Java 9中,这变得更加简洁,因为你可以对匿名类使用“钻石形式”:
TypeToken<List<Sample>> sampleListType = new TypeToken<>() {};
个在Java 10中,你也可以使用
var
:var sampleListType = new TypeToken<List<Sample>>() {};
个[1]例如,
Gson.fromJson(..., Type)
允许您编写这样的非类型安全代码,它可以在没有警告的情况下编译,但在运行时失败:型