Gson可选和必填字段

一个人应该如何处理Gson和需要与可选字段?

由于所有字段都是可选的,所以我不能根据响应json是否包含某个键来真正地失败我的networking请求, Gson将简单地将其parsing为null。

方法我正在使用gson.fromJson(json, mClassOfT);

例如,如果我有以下json:

 {"user_id":128591, "user_name":"TestUser"} 

而我的class级:

 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; } } 

如果json不包含user_iduser_name键,是否有任何选项可以让Gson失败?

可能有很多情况下,您可能需要至less一些值来parsing和其他可能是可选的?

是否有任何模式或图书馆被用来处理这个案件全球?

谢谢。

正如你所看到的,Gson没有工具来定义一个“必填字段”,如果在JSON中缺less某些东西,你只需要在反序列化的对象中得到null

这是一个可重复使用的反序列化器和注解。 限制是,如果POJO需要一个自定义的反序列化器,你将不得不进一步,并在构造函数中传入一个Gson对象来反序列化以自我对象或将注释检出移入一个单独的方法在你的解串器中使用它。 您也可以通过创build自己的exception并将其传递给JsonParseException来改进exception处理,以便可以通过调用程序中的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”中的exceptioncom.google.gson.JsonParseException:JSON中缺less字段:foo

这是我简单的解决scheme,创build一个最小编码的通用解决scheme。

  1. 创build@可选注释
  2. 先标记可选。 假定rest是可选的。 以前是假定需要的。
  3. 创build一个通用的“loader”方法来检查源Json对象是否有值。 一旦遇到@Optional字段,循环停止。

我正在使用子类化,所以咕噜的工作是在超类中完成的。

这是超类代码。

 import com.google.gson.Gson; import java.lang.reflect.Field; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; ... @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Optional { public boolean enabled() default true; } 

和咕噜的工作方法

 @SuppressWarnings ("unchecked") public <T> T payload(JsonObject oJR,Class<T> T) throws Exception { StringBuilder oSB = new StringBuilder(); String sSep = ""; Object o = gson.fromJson(oJR,T); // Ensure all fields are populated until we reach @Optional Field[] oFlds = T.getDeclaredFields(); for(Field oFld:oFlds) { Annotation oAnno = oFld.getAnnotation(Optional.class); if (oAnno != null) break; if (!oJR.has(oFld.getName())) { oSB.append(sSep+oFld.getName()); sSep = ","; } } if (oSB.length() > 0) throw CVT.e("Required fields "+oSB+" mising"); return (T)o; } 

和使用的一个例子

 public static class Payload { String sUserType ; String sUserID ; String sSecpw ; @Optional String sUserDev ; String sUserMark ; } 

和填充代码

 Payload oPL = payload(oJR,Payload.class); 

在这种情况下,sUserDev和sUserMark是可选的,其余的都是必需的。 该解决scheme依赖于这个类存储在声明的顺序字段定义的事实。