如果pojo不包含json中指定的字段,则将Gson反序列化到Pojo失败

时间:2016-07-19 04:01:04

标签: gson

给出以下json文件:

{
    "validField":"I'm here",
    "invalidField":"I'm not here :-(",
}

和Pojo

public class Pojo {
    public String validField;
}

当我使用gson将json反序列化为Pojo时,我希望它在invalidField上失败,因为它在Pojo中不存在。

// This should fail but just ignores 'invalidField' property
Pojo pojo = new Gson().fromJson(json, Pojo.class);

任何想法如何实现这一目标?

1 个答案:

答案 0 :(得分:0)

缺乏替代方案我想出了以下内容。我仍然希望听到是否有支持的解决方案。

private static void validateAllDataLoaded(JsonElement element, Object returnType, String entryName) throws IOException {

    if (element.isJsonNull()) {
        return;
    }

    if (element.isJsonArray()) {
        checkFieldExists(entryName, returnType);

        for (Object arrayItem : (ArrayList<?>) returnType) {
            for (JsonElement item : element.getAsJsonArray()) {
                validateAllDataLoaded(item, arrayItem, entryName);
            }
        }
    }

    if (element.isJsonObject()) {
        checkFieldExists(entryName, returnType);

        for (Map.Entry<String, JsonElement> entry : element.getAsJsonObject().entrySet()) {
            if (!entry.getValue().isJsonNull() && !entry.getValue().isJsonPrimitive()) {
                validateAllDataLoaded(entry.getValue(), getField(entry.getKey(), returnType), "");
            } else {
                validateAllDataLoaded(entry.getValue(), returnType, entry.getKey());
            }
        }
    }

    if (element.isJsonPrimitive()) {
        checkFieldExists(entryName, returnType);
    }
}

private static void checkFieldExists(String entryName, Object returnType) throws IOException {
    if (entryName.isEmpty()) {
        return;
    }

    Field[] fields = returnType.getClass().getDeclaredFields();
    boolean exists = Arrays.asList(fields).stream().filter(f -> f.getName().equals(entryName)).count() == 1;

    if (!exists) {
        throw new IOException("JSON element '" + entryName + "' is not a field in the destination class " + returnType.getClass().getName());
    }
}

private static Object getField(String entryName, Object returnType) throws IOException {
    if (entryName.isEmpty()) {
        return null;
    }

    Field field;
    try {
        field = returnType.getClass().getDeclaredField(entryName);
        field.setAccessible(true);

        return field.get(returnType);
    } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
        throw new IOException(e);
    }
}