Gson与可选字段相比,应如何处理?
Gson
由于所有字段都是可选的,因此我无法根据响应json是否包含某些密钥来真正使我的网络请求失败,Gson只需将其解析为null。
我正在使用的方法 gson.fromJson(json, mClassOfT);
gson.fromJson(json, mClassOfT);
例如,如果我有以下json:
{"user_id":128591, "user_name":"TestUser"}
而我的班级:
public class User { @SerializedName("user_id") private String mId; @SerializedName("user_name") private String mName; public String getId() { return mId; } public void setId(String id) { mId = id; } public String getName() { return mName; } public void setName(String name) { mName = name; } }
Gson如果json不包含user_id或不包含user_name密钥,是否有任何选择会失败?
user_id
user_name
在许多情况下,您可能至少需要解析一些值,而其他值是可选的?
是否有任何模式或库可用于全局处理这种情况?
谢谢。
如您所述,Gson无法定义“必填字段”,并且null如果JSON中缺少某些内容,您只会进入反序列化的对象。
null
这是一个可重复使用的反序列化器和注释,它将完成此任务。局限性在于,如果POJO仍然需要自定义反序列化器,则您必须走得更远,或者Gson在构造函数中传入一个对象以反序列化为对象本身,或者将注解签出到单独的方法中并使用它在您的解串器中。您还可以通过创建自己的异常并将其传递给来改进异常处理,JsonParseException以便可以getCause()在调用方中对其进行检测。
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; } }
输出:
这是foo 这是酒吧 这是foo 空值 线程“ main” com.google.gson.JsonParseException中的异常:JSON中的字段缺失:foo