如何在反序列化JSON响应中处理Gson的NumberFormatException

2022-08-31 17:36:16

我正在阅读带有Gson的JSON响应,它有时会返回a,因为预期值设置为空字符串。现在我想知道处理这种异常的最佳方法是什么。如果该值为空字符串,则反序列化应为 0。NumberFormatExceptionint

预期的 JSON 响应:

{
   "name" : "Test1",
   "runtime" : 90
}

但有时运行时是一个空字符串:

{
   "name" : "Test2",
   "runtime" : ""
}

java 类如下所示:

public class Foo
{
    private String name;
    private int runtime;
}

反序列化是这样的:

String input = "{\n" +
               "   \"name\" : \"Test\",\n" +
               "   \"runtime\" : \"\"\n" +
               "}";

Gson gson = new Gson();
Foo foo = gson.fromJson(input, Foo.class);

这会引发 a,因为返回的是空字符串而不是 int 值。com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: empty String

有没有办法告诉Gson,“如果你反序列化Type Foo的字段运行时并且有一个NumberFormatException,只需返回默认值0”?

我的解决方法是使用 a 作为字段的类型,而不是 ,但也许有更好的方法来处理此类错误。Stringruntimeint


答案 1

这是我为类型制作的一个示例。这是一个更好的选择:Long

public class LongTypeAdapter extends TypeAdapter<Long> {

    @Override
    public Long read(JsonReader reader) throws IOException {
        if (reader.peek() == JsonToken.NULL) {
            reader.nextNull();
            return null;
        }
        String stringValue = reader.nextString();
        try {
            Long value = Long.valueOf(stringValue);
            return value;
        } catch (NumberFormatException e) {
            return null;
        }
    }

    @Override
    public void write(JsonWriter writer, Long value) throws IOException {
        if (value == null) {
            writer.nullValue();
            return;
        }
        writer.value(value);
    }
}

使用 util 注册适配器:Gson

Gson gson = new GsonBuilder().registerTypeAdapter(Long.class, new LongTypeAdapter()).create();

您可以参考此链接了解更多信息。


答案 2

起初,我尝试为整数值编写一个通用的自定义类型适配器,以捕获并返回0,但Gson不允许基元类型的TypeAdaptors:NumberFormatException

java.lang.IllegalArgumentException: Cannot register type adapters for class java.lang.Integer

之后,我为该字段引入了一个新的 Type,因此该类现在如下所示:FooRuntimeruntimeFoo

public class Foo
{
    private String name;
    private FooRuntime runtime;

    public int getRuntime()
    {
        return runtime.getValue();
    }
}

public class FooRuntime
{
    private int value;

    public FooRuntime(int runtime)
    {
        this.value = runtime;
    }

    public int getValue()
    {
        return value;
    }
}

类型适配器处理自定义反序列化过程:

public class FooRuntimeTypeAdapter implements JsonDeserializer<FooRuntime>, JsonSerializer<FooRuntime>
{
    public FooRuntime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
    {
        int runtime;
        try
        {
            runtime = json.getAsInt();
        }
        catch (NumberFormatException e)
        {
            runtime = 0;
        }
        return new FooRuntime(runtime);
    }

    public JsonElement serialize(FooRuntime src, Type typeOfSrc, JsonSerializationContext context)
    {
        return new JsonPrimitive(src.getValue());
    }
}

现在有必要使用 来注册类型适配器,因此空字符串被解释为 0 而不是抛出 .GsonBuilderNumberFormatException

String input = "{\n" +
               "   \"name\" : \"Test\",\n" +
               "   \"runtime\" : \"\"\n" +
               "}";

GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(FooRuntime.class, new FooRuntimeTypeAdapter());
Gson gson = builder.create();
Foo foo = gson.fromJson(input, Foo.class);