如何使用gson反序列化base64编码的json数据 [英] how to deserialize base64 encoded json data with gson
问题描述
我有一个像这样的json:
I have a json like this:
{code:1, message:"ok", data:"W3tpZDoxLCBuYW1lOiJUb20ifSx7aWQ6MiwgbmFtZToiSmFjayJ9LHtpZDozLCBuYW1lOiJMdWNpYSJ9XQ=="}
,只有数据是使用base64编码的,实际数据是:
, only data is encoded using base64, the real data is:
[{id:1, name:"Tom"},{id:2, name:"Jack"},{id:3, name:"Lucia"}]
.如何使用gson一步反序列化此json?
. How to use gson to deserialize this json in one step?
推荐答案
Gson在此处提出了几个选择,但以下似乎是最短的选择.考虑以下 Response
和 User
类:
Gson suggests a couple of options here, but the following seems to be the shortest one. Consider the following Response
and User
classes:
final class Response<T> {
@SerializedName("code")
final int code = Integer.valueOf(0);
@SerializedName("message")
final String message = null;
@SerializedName("data")
@JsonAdapter(Base64TypeAdapterFactory.class)
final T data = null;
}
final class User {
final int id = Integer.valueOf(0);
final String name = null;
@Override
public String toString() {
return id + ":" + name;
}
}
上面的
@JsonAdapter(Base64TypeAdapterFactory.class)
告诉Gson为给定字段选择一个特殊类型的适配器.此类型适配器将负责Base64解码,并且可以在反序列化过程中使用类型令牌对实际类型进行专门化.
@JsonAdapter(Base64TypeAdapterFactory.class)
above tells Gson to pick a special type adapter for the given field.
This type adapter will be responsible for Base64 decoding and the actual type can be specialized using type tokens during deserialization.
final class Base64TypeAdapterFactory
implements TypeAdapterFactory {
// Gson can instantiate this one itself, no need to expose it
private Base64TypeAdapterFactory() {
}
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
final TypeAdapter<String> stringTypeAdapter = gson.getAdapter(String.class);
final TypeAdapter<T> dataTypeAdapter = gson.getAdapter(typeToken);
return Base64TypeAdapter.of(stringTypeAdapter, dataTypeAdapter);
}
private static final class Base64TypeAdapter<T>
extends TypeAdapter<T> {
private static final Decoder base64Decoder = Base64.getDecoder();
private final TypeAdapter<String> stringTypeAdapter;
private final TypeAdapter<T> dataTypeAdapter;
private Base64TypeAdapter(final TypeAdapter<String> stringTypeAdapter, final TypeAdapter<T> dataTypeAdapter) {
this.stringTypeAdapter = stringTypeAdapter;
this.dataTypeAdapter = dataTypeAdapter;
}
static <T> TypeAdapter<T> of(final TypeAdapter<String> stringTypeAdapter, final TypeAdapter<T> dataTypeAdapter) {
return new Base64TypeAdapter<>(stringTypeAdapter, dataTypeAdapter)
.nullSafe(); // Just let Gson manage nulls itself. It's convenient
}
@Override
public void write(final JsonWriter jsonWriter, final T value) {
throw new UnsupportedOperationException();
}
@Override
public T read(final JsonReader jsonReader)
throws IOException {
// Decode the payload first as a Base64-encoded message
final byte[] payload = base64Decoder.decode(stringTypeAdapter.read(jsonReader));
try ( final JsonReader payloadJsonReader = new JsonReader(new InputStreamReader(new ByteArrayInputStream(payload))) ) {
// And tell Gson to not refuse unquoted property names
payloadJsonReader.setLenient(true);
return dataTypeAdapter.read(payloadJsonReader);
} catch ( final EOFException ignored ) {
return null;
}
}
}
}
现在您可以轻松对其进行测试:
Now you can easily test it:
final Response<List<User>> response = gson.fromJson(..., new TypeToken<Response<List<User>>>() {
}.getType());
System.out.println(response.code);
System.out.println(response.message);
System.out.println(response.data);
输出:
1
ok
[1:Tom, 2:Jack, 3:Lucia]
这篇关于如何使用gson反序列化base64编码的json数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!