不幸的是,那里的文档有点误导。
只有当你的类有一个字段的类型与 JSON 中的不匹配时,它才会抛出异常,即使这样,它也会做一些疯狂的事情来尝试修复它(例如将int
JSON 中的 a转换为String
你的类中的a )。如果您的 POJO 中有类似字段的内容,并且在 JSON 中Date
遇到了一个字段,它会抛出它。int
JSON 中存在但 POJO 中不存在的字段将被静默忽略,JSON 中缺少但存在于 POJO 中的字段设置为null
.
目前,GSON 没有为任何类型的“严格”反序列化提供机制,在这种反序列化中,您可能会@Required
在 POJO 中为字段添加注释。
在你的情况下......我只是扩展我的 POJO 以包含一个内部错误对象......就像:
class Dummy {
private String foo;
private int bar;
private Error error;
private class Error {
String publicMsg;
String msg;
}
public boolean isError() {
return error != null;
}
// setters and getters for your data, the error msg, etc.
}
您的另一个选择是编写一个自定义反序列化程序,如果 JSON 是错误,则抛出异常,例如:
class MyDeserializer implements JsonDeserializer<Dummy>
{
@Override
public Dummy deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException
{
JsonObject jsonObject = (JsonObject) json;
if (jsonObject.get("error") != null)
{
throw new JsonParseException("Error!");
}
return new Gson().fromJson(json, Dummy.class);
}
}
编辑添加:最近有人对此表示赞同并重新阅读它,我想“嗯,你知道,你可以自己做这个,它可能会很方便”。
这是一个可重复使用的反序列化器和注释,它将完全符合 OP 的要求。限制是,如果 POJO 需要按原样自定义反序列化器,则您必须更进一步,要么在构造函数中传入一个Gson
对象以反序列化为对象本身,要么将注解检出到单独的方法中并使用它在你的反序列化器中。您还可以通过创建自己的异常并将其传递给来改进异常处理,JsonParseException
以便可以getCause()
在调用者中检测到它。
综上所述,在绝大多数情况下,这将起作用:
public class App
{
public static void main(String[] args)
{
Gson gson =
new GsonBuilder()
.registerTypeAdapter(TestAnnotationBean.class, new AnnotatedDeserializer<TestAnnotationBean>())
.create();
String json = "{\"foo\":\"This is foo\",\"bar\":\"this is bar\"}";
TestAnnotationBean tab = gson.fromJson(json, TestAnnotationBean.class);
System.out.println(tab.foo);
System.out.println(tab.bar);
json = "{\"foo\":\"This is foo\"}";
tab = gson.fromJson(json, TestAnnotationBean.class);
System.out.println(tab.foo);
System.out.println(tab.bar);
json = "{\"bar\":\"This is bar\"}";
tab = gson.fromJson(json, TestAnnotationBean.class);
System.out.println(tab.foo);
System.out.println(tab.bar);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface JsonRequired
{
}
class TestAnnotationBean
{
@JsonRequired public String foo;
public String bar;
}
class AnnotatedDeserializer<T> implements JsonDeserializer<T>
{
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException
{
T pojo = new Gson().fromJson(je, type);
Field[] fields = pojo.getClass().getDeclaredFields();
for (Field f : fields)
{
if (f.getAnnotation(JsonRequired.class) != null)
{
try
{
f.setAccessible(true);
if (f.get(pojo) == null)
{
throw new JsonParseException("Missing field in JSON: " + f.getName());
}
}
catch (IllegalArgumentException ex)
{
Logger.getLogger(AnnotatedDeserializer.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IllegalAccessException ex)
{
Logger.getLogger(AnnotatedDeserializer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
return pojo;
}
}
输出:
这是富
这是酒吧
这是富
空值
线程“主”com.google.gson.JsonParseException 中的异常:JSON 中缺少字段:foo