我有一个来自SDK但没有权限进行更改的课程,但是我想将一个JSON有效的字符串序列化为。
但是,外部API有时会为Date字段输入错误的类型。
长话短说:我可以忽略GSON中的错误,或者告诉Gson忽略字段上的错误,然后获取部分对象吗?
例如,该字段应为double,但我得到一个Date(数字)。但是我还是没有使用它,所以我不在乎,我也不需要整个过程失败。我只想要parcable字段,故障字段保留为null。
注意:编写一个反序列化器来创建我想要由Gson创建的对象,这违背了我提出的目的。
这是一行失败的代码,因为单个字段是错误的:
Customer customer = gson.fromJson(settings.getCustomerObjectJSONString(), Customer.class);
我希望它只是跳过它无法解析的字段,因为我无法访问Customer类,因为它来自生成的SDK /库。
答案 0 :(得分:1)
我知道有两种选择。
您可以使用 JSON反序列化程序实现来自行解析JSON元素。但是,以下示例将影响传递给该单个double
实例的任何DTO的所有Double
和gson
字段,并且此类行为可以是可解除的。不幸的是,我不知道是否可以以“上下文”的方式使用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 foo bar
0.0 null foo bar
的
{"primitive": 23, "nullable": 42, "string": "foo bar"}
{"primitive": "whatever", "nullable": {"subValue": "whatever"}, "string": "foo bar"}
有效载荷。
答案 1 :(得分:1)
我从另一个角度看问题,即OP中提到的主要要求是
1)您不关心特定领域中存在的值
2)您不会使用特定字段值,也不希望解串器因数据无效而失败
在上述情况下,您可以将特定字段标记为TRANSIENT或STATIC。默认情况下,Gson将排除所有标记为瞬态或静态的字段。
示例: - 强>
private transient Date joiningDate;