不幸的是,文档在那里有点误导。
仅当您的类具有类型与JSON中的内容不匹配的字段时,它才会引发异常,即使这样,它也会做一些疯狂的事情来尝试修复它(例如,将JSON中的a转换为类中的a)。如果你的POJO中有一个类似字段的东西,并且在JSON中遇到一个,它会抛出它。JSON 中存在但 POJO 中不存在的字段将被静默忽略,JSON 中缺少但 POJO 中存在的字段将设置为 。int
String
Date
int
null
目前,GSON没有为任何类型的“严格”反序列化提供一种机制,在这种反序列化中,您将拥有类似POJO中字段的注释之类的东西。@Required
在您的情况下...我只是简单地扩展我的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;
}
}
输出:
This is foo
this is bar
This is foo
null
Exception in thread "main" com.google.gson.JsonParseException: Missing field in JSON: foo