I'm reading a JSON response with Gson, which returns somtimes a NumberFormatException because an expected int value is set to an empty string. Now I'm wondering what's the best way to handle this kind of exception. If the value is an empty string, the deserialization should be 0.

Expected JSON response:

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

But sometimes the runtime is an empty string:

{
   "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);

Which throws a com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: empty String because an empty String is returned instead of an int value.

Is there a way to tell Gson, "if you deserialize the field runtime of the Type Foo and there is a NumberFormatException, just return the default value 0"?

My workaround is to use a String as the Type of the runtime field instead of int, but maybe there is a better way to handle such errors.

推荐答案

At first, I tried to write a general custom type adaptor for Integer values, to catch the NumberFormatException and return 0, but Gson doesn't allow TypeAdaptors for primitive Types:

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

之后,我为runtime字段引入了一个新的类型FooRuntime,所以Foo类现在看起来像这样:

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

A type adaptor handles the custom deserialization process:

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

Now it's necessary to use GsonBuilder to register the type adapter, so an empty string is interpreted as 0 instead of throwing a NumberFormatException.

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

Json相关问答推荐

try 将文本标记放置在条形图上的同一高度

JOLT拉平数组

在scala中将字符串列转换为 struct 的JSON映射

当console.log返回TRUE值时,解析的JSON中的字段未定义

写入JSON文件的流

NiFi QueryRecord处理器- Select 可选的JSON属性

来自json的可分析的构建报告

重构JOLT代码以获得预期输出

如何使用 JOLT 使用输入数组中的值和层次 struct 中的其他字段创建数组

Jolt 不打印任何东西

如何使用 serde_json 构建有状态的流式解析器?

从 json 数组中仅提取一个值导致 vb6

N1QL 聚合查询 Couchbase

为什么在测试 RSPEC 时 JBuilder 不返回 JSON 中的响应正文

在 JSON 字符串中react i18n 换行符

使用 c# 通用地展平 Json

如何在已声明的 JSON 对象中添加键值对

如何向(JSON)对象的原型添加方法?

Javascript:如何判断 AJAX 响应是否为 JSON

从 JSON 中 Select 不同的值