当预期的字符串数组返回对象时,Gson引发异常

时间:2018-10-20 14:49:20

标签: json gson

我正在使用一个api,其中一个特定字段(下面)通常包含一个字符串数组。但是,如果数组为空,则api在通常为字符串数组的形式中返回一个空对象。这是引起问题的领域。

正常。

"a": [
    "str"
    ]

空。

"a": [
    {}
    ]

第二种情况导致Gson崩溃,并抛出JsonSyntaxException。我该如何处理?

2 个答案:

答案 0 :(得分:1)

让我们假设您有一个表示API响应的类,例如:

public class Response {
    private String[] a;
    private String b;
    private String c;
}

获取Response对象的一种方法来解析a的JSON是否有效是创建JsonDeserializer来检查a是否可以解析并排除解析的一种方法。 a如果失败,则将a留给null

public class SkipBadSyntaxDeserializer implements JsonDeserializer<Response> {

    // This strategy is used if parse of field a fails
    private final ExclusionStrategy excludeA = new ExclusionStrategy() {
        @Override
        public boolean shouldSkipField(FieldAttributes f) {
            return "a".equals(f.getName());
        }

        // no need to care of this used only here for the Response class
        @Override
        public boolean shouldSkipClass(Class<?> clazz) {
            return false;
        }
    };

    // one parser for good and another for bad format
    private final Gson gson = new Gson(),
            gsonBadFormat = new GsonBuilder()
                    .addDeserializationExclusionStrategy(excludeA).create();;

    @Override
    public Response deserialize(JsonElement json, Type typeOfT, 
                JsonDeserializationContext context)
            throws JsonParseException {
        try {
            return gson.fromJson(json, Response.class);
        } catch (JsonSyntaxException e) {
            // parse a failed try again without it  
            return gsonBadFormat.fromJson(json, Response.class);
        }

    }

}

尝试:

new GsonBuilder().registerTypeAdapter(Response.class,
            new SkipBadSyntaxDeserializer())
                 .create()
                 .fromJson(JSON, Response.class);

如果JSON是这样的:

{
    "a": [{}],
    "b": "bval",
    "c": "cval"   
}

然后Response的属性为:

a=null
b="bval"
c="cval"

更新

根据您自己的答案:如果可以更改DTO进行响应,则使用注释@JsonAdapter将使您可以按字段处理此问题。反序列化器将很简单:

public class SkipExceptionAdapter implements JsonDeserializer<String[]> {
    @Override
    public String[] deserialize(JsonElement json, Type typeOfT,
                JsonDeserializationContext context)
            throws JsonParseException {
        try {
            return context.deserialize(json, String[].class);
        } catch (JsonSyntaxException e) {
            return new String[] {}; // or null how you wish
        }
    }
}

Response.a

中的注释
@JsonAdapter(SkipExceptionAdapter.class)
private String[] a;

将仅针对该字段进行处理。

答案 1 :(得分:1)

我不知道这是否是最好的方法,但是它可以工作。

可以使用@JsonAdapter(MyTypeAdapter.class)注释错误字段。然后,TypeAdapter可以使用其read方法并使用peek()weather检查下一个值是否不是预期的类型。