我知道两种选择。
您可以使用 JSON 反序列化器 实现自行解析 JSON 元素。但是,对于传递给单个 gson 实例的任何 DTO,以下示例将影响所有 double 和 Double 字段,并且这种行为可能是不可取的。不幸的是,我不知道是否可以以“上下文”方式使用JsonDeserializer:例如如果它们是某个父类的字段,则让它适用于所有 double 和 Double 字段。
private static final class Dto {
private double primitive;
private Double nullable;
private String string;
}
private static final class FailSafeDoubleJsonDeserializer
implements JsonDeserializer<Double> {
@Override
public Double deserialize(final JsonElement element, final Type type, final JsonDeserializationContext context)
throws JsonParseException {
if ( !element.isJsonPrimitive() ) {
return null;
}
try {
final JsonPrimitive primitive = (JsonPrimitive) element;
final Number number = primitive.getAsNumber();
return number.doubleValue();
} catch ( final NumberFormatException ignored ) {
return null;
}
}
}
private static final JsonDeserializer<Double> failSafeDoubleJsonDeserializer = new FailSafeDoubleJsonDeserializer();
private static final Gson gson = new GsonBuilder()
.registerTypeAdapter(double.class, failSafeDoubleJsonDeserializer)
.registerTypeAdapter(Double.class, failSafeDoubleJsonDeserializer)
.create();
public static void main(final String... args) {
dump(gson.fromJson("{\"primitive\": 23, \"nullable\": 42, \"string\": \"foo bar\"}", Dto.class));
dump(gson.fromJson("{\"primitive\": \"whatever\", \"nullable\": \"whatever\", \"string\": \"foo bar\"}", Dto.class));
}
private static void dump(final Dto dto) {
out.println(dto.primitive + " " + dto.nullable + " " + dto.string);
}
另一个更底层的选项可以是类型适配器实现。与上一个示例相比,此示例的一个优点是您可以在已知可能损坏的 DTO 类中使用 @JsonAdapter 注释来注释失败的字段。
private static final class Dto {
@JsonAdapter(FailSafeDoubleTypeAdapter.class)
private double primitive;
@JsonAdapter(FailSafeDoubleTypeAdapter.class)
private Double nullable;
private String string;
}
private static final class FailSafeDoubleTypeAdapter
extends TypeAdapter<Double> {
@Override
public void write(final JsonWriter writer, final Double value) {
throw new UnsupportedOperationException();
}
@Override
public Double read(final JsonReader reader)
throws IOException {
final JsonToken peek = reader.peek();
if ( peek != NUMBER ) {
reader.skipValue();
return null;
}
return reader.nextDouble();
}
}
private static final Gson gson = new Gson();
public static void main(final String... args) {
dump(gson.fromJson("{\"primitive\": 23, \"nullable\": 42, \"string\": \"foo bar\"}", Dto.class));
dump(gson.fromJson("{\"primitive\": \"whatever\", \"nullable\": {\"subValue\": \"whatever\"}, \"string\": \"foo bar\"}", Dto.class));
}
private static void dump(final Dto dto) {
out.println(dto.primitive + " " + dto.nullable + " " + dto.string);
}
因此,两个示例都会生成以下输出:
23.0 42.0 富吧
0.0 空 foo 栏
为
{"primitive": 23, "nullable": 42, "string": "foo bar"}
- 和
{"primitive": "whatever", "nullable": {"subValue": "whatever"}, "string": "foo bar"}
有效载荷。