我有一个像这样的json:
{code:1, message:"ok", data:"W3tpZDoxLCBuYW1lOiJUb20ifSx7aWQ6MiwgbmFtZToiSmFjayJ9LHtpZDozLCBuYW1lOiJMdWNpYSJ9XQ=="}
,只有数据使用base64编码,真实数据是:
[{id:1, name:"Tom"},{id:2, name:"Jack"},{id:3, name:"Lucia"}]
。如何使用gson一步反序化这个json?
答案 0 :(得分:1)
Gson在这里提出了几个选择,但以下似乎是最短的选择。请考虑以下Response
和User
类:
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解码,并且在反序列化期间可以使用类型令牌来专门化实际类型。
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;
}
}
}
}
现在您可以轻松测试它:
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]