假设我正在使用Google的Gson库将JSON解析为Java数据结构。
如果Java字段没有对应的JSON,是否有一种简单的引发异常的方法?也就是说,我希望要求JSON具有Java结构中的所有字段。
Gson没有JSON模式验证功能来指定必须存在一个特定的元素,也没有办法指定必须填充Java成员。拥有这样的功能(例如带有@Required注释)可能会很好。转到“ Gson问题列表”并提出增强请求。
@Required
使用Gson,您可以强制使用自定义反序列化器提供指定的JSON元素。
// output: // [MyObject: element1=value1, element2=value2, element3=value3] // [MyObject: element1=value1, element2=value2, element3=null] // Exception in thread "main" com.google.gson.JsonParseException: Required Field Not Found: element2 import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; public class Foo { static String jsonInput1 = "{\"element1\":\"value1\",\"element2\":\"value2\",\"element3\":\"value3\"}"; static String jsonInput2 = "{\"element1\":\"value1\",\"element2\":\"value2\"}"; static String jsonInput3 = "{\"element1\":\"value1\",\"element3\":\"value3\"}"; public static void main(String[] args) { GsonBuilder gsonBuilder = new GsonBuilder(); MyDeserializer deserializer = new MyDeserializer(); deserializer.registerRequiredField("element2"); gsonBuilder.registerTypeAdapter(MyObject.class, deserializer); Gson gson = gsonBuilder.create(); MyObject object1 = gson.fromJson(jsonInput1, MyObject.class); System.out.println(object1); MyObject object2 = gson.fromJson(jsonInput2, MyObject.class); System.out.println(object2); MyObject object3 = gson.fromJson(jsonInput3, MyObject.class); System.out.println(object3); } } class MyObject { String element1; String element2; String element3; @Override public String toString() { return String.format( "[MyObject: element1=%s, element2=%s, element3=%s]", element1, element2, element3); } } class MyDeserializer implements JsonDeserializer<MyObject> { List<String> requiredFields = new ArrayList<String>(); void registerRequiredField(String fieldName) { requiredFields.add(fieldName); } @Override public MyObject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = (JsonObject) json; for (String fieldName : requiredFields) { if (jsonObject.get(fieldName) == null) { throw new JsonParseException("Required Field Not Found: " + fieldName); } } return new Gson().fromJson(json, MyObject.class); } }
一种更好的方法可能是使用提供JSON模式验证的API 。 杰克逊至少有一个基本的实施方案。 JSON工具似乎已经成熟了。
这是杰克逊的一个例子。
// output: // Validating jsonInput1... // Validating jsonInput2... // Validating jsonInput3... // $.element2: is missing and it is not optional // [MyObject: element1=value1, element2=value2, element3=value3] // [MyObject: element1=value1, element2=value2, element3=null] // [MyObject: element1=value1, element2=null, element3=value3] import java.util.List; import org.codehaus.jackson.map.ObjectMapper; import eu.vahlas.json.schema.JSONSchema; import eu.vahlas.json.schema.JSONSchemaProvider; import eu.vahlas.json.schema.impl.JacksonSchemaProvider; public class Foo { static String jsonSchema = "{" + "\"description\":\"Serialized MyObject Specification\"," + "\"type\":[\"object\"]," + "\"properties\":" + "{" + "\"element1\":{\"type\":\"string\"}," + "\"element2\":{\"type\":\"string\",\"optional\":false}," + "\"element3\":{\"type\":\"string\",\"optional\":true}" + "}" + "}";; static String jsonInput1 = "{\"element1\":\"value1\",\"element2\":\"value2\",\"element3\":\"value3\"}"; static String jsonInput2 = "{\"element1\":\"value1\",\"element2\":\"value2\"}"; static String jsonInput3 = "{\"element1\":\"value1\",\"element3\":\"value3\"}"; public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); JSONSchemaProvider schemaProvider = new JacksonSchemaProvider(mapper); JSONSchema schema = schemaProvider.getSchema(jsonSchema); System.out.println("Validating jsonInput1..."); validateAndLogErrors(jsonInput1, schema); System.out.println("Validating jsonInput2..."); validateAndLogErrors(jsonInput2, schema); System.out.println("Validating jsonInput3..."); validateAndLogErrors(jsonInput3, schema); MyObject object1 = mapper.readValue(jsonInput1, MyObject.class); System.out.println(object1); MyObject object2 = mapper.readValue(jsonInput2, MyObject.class); System.out.println(object2); MyObject object3 = mapper.readValue(jsonInput3, MyObject.class); System.out.println(object3); } static void validateAndLogErrors(String jsonInput, JSONSchema schema) { List<String> errors = schema.validate(jsonInput); for (String error : errors) { System.out.println(error); } } } class MyObject { String element1; String element2; String element3; void setElement1(String element1) { this.element1 = element1; } void setElement2(String element2) { this.element2 = element2; } void setElement3(String element3) { this.element3 = element3; } @Override public String toString() { return String.format( "[MyObject: element1=%s, element2=%s, element3=%s]", element1, element2, element3); } }