是否有可能允许Gson只是跳过字段的错误类型



我有一个来自SDK的类,我无法访问更改,但我想将json有效的字符串序列化为。

但是,外部API有时会为Date字段输入错误的类型。

长话短说:我可以忽略GSON中的错误,或者告诉GSON忽略字段上的错误,只是得到部分对象吗?

例如,该字段应该是双精度类型,但我得到的却是Date(number)。但反正我不会用它,所以我不在乎,我也不希望整个过程失败。我只是想把可分割的字段拿出来,错误的字段为空。

注意:编写一个反序列化器来创建我想由Gson创建的对象,这违背了我提出的目的。

这是一行失败的代码,因为单个字段是错误的:

Customer customer = gson.fromJson(settings.getCustomerObjectJSONString(), Customer.class);

我希望它只是跳过它无法解析的字段,因为我无法访问Customer类,因为它来自生成的SDK/库。

我知道有两个选择。

你可以使用一个JSON反序列化器实现来自己解析JSON元素。然而,对于传递给单个gson实例的任何dto,下面的示例将影响所有doubleDouble字段,并且这样的行为可能是可取的。不幸的是,我不知道是否有可能在"上下文中"使用JsonDeserializer。方法:例如,让它对所有doubleDouble字段工作,如果这些字段是某个父类的字段。

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);
}

因此,两个示例都生成以下输出:

foo bar

0.0 null foo bar

  • {"primitive": 23, "nullable": 42, "string": "foo bar"}
  • {"primitive": "whatever", "nullable": {"subValue": "whatever"}, "string": "foo bar"}

分别载荷。

我从另一个角度看问题,即OP中提到的主要要求是

1)你不关心特定字段

中的值

2)您不打算使用特定的字段值,并且不希望反序列化器因为无效数据

而失败

在上面的例子中,您可以将特定字段标记为TRANSIENT或STATIC。默认情况下,Gson将排除所有标记为瞬态或静态的字段。

: -

private transient Date joiningDate;

最新更新