Java 检查json属性是否存在、是否为字符串以及值是否正确
使用gson,我使用这种繁琐的方法来确保所需的属性具有所需的值:Java 检查json属性是否存在、是否为字符串以及值是否正确,java,json,gson,Java,Json,Gson,使用gson,我使用这种繁琐的方法来确保所需的属性具有所需的值: import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; public class ScratchSpace { public static void main(String[] args) { // create json object from
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class ScratchSpace {
public static void main(String[] args) {
// create json object from source data - in my real code, this is sourced externally
JsonObject json = new JsonParser().parse("{ \"product\": \"foobar\"}").getAsJsonObject();
// does this object have a key called product, which is a string, and equal to our expected value?
boolean correctProduct = false;
if (json.has("product")) {
JsonElement productElement = json.get("product");
if (productElement.isJsonPrimitive()) {
String product = productElement.getAsString();
if ("foobar".equals(product)) {
correctProduct = true;
}
}
}
System.out.println("correctProduct = " + correctProduct);
}
}
我几乎可以肯定我做得不太好。是否有一个简单、易读、简短的一行程序可以达到同样的效果
编辑:如果可能的话,我想继续使用gson。使用
java.util.Optional
,下面的工作:
final boolean correctProduct = Optional.ofNullable(json.get("product"))
.filter(JsonPrimitive.class::isInstance)
.map(JsonPrimitive.class::cast)
.map(JsonPrimitive::getAsString)
.filter("foobar"::equals)
.isPresent();
您可以编写一个自定义的反序列化程序,如,注册它,并使用方法直接从json字符串获取对象。这样,如果json字符串不是预期的格式,您可以返回
null
或在反序列化程序中抛出异常
请注意,您不必单独设置每个字段。执行自定义检查后,可以使用上下文中的默认反序列化
编辑:如果只想获得true
/false
而不是完整的对象,那么可以编写一个MyBoolean
类,持有一个简单的boolean
值,并使用fromJson
方法反序列化为MyBoolean
类。自定义反序列化程序将仅执行所需的检查,并适当设置MyBoolean
实例的内容。此外,(我猜)如果你从布尔扩展这个MyBoolean
,你也可以将它用作Boolean
编辑2:我以前没有时间包含示例代码。以下是我的建议:
package io.ram.ram;
import java.lang.reflect.Type;
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.JsonParseException;
public class Tester {
public static class MyBoolean {
private boolean value;
public void set(boolean value) {
this.value = value;
}
public boolean get() {
return value;
}
}
public static class MyAdapter implements JsonDeserializer<MyBoolean> {
public MyBoolean deserialize(JsonElement json, Type type, JsonDeserializationContext context)
throws JsonParseException {
MyBoolean result = new MyBoolean();
result.set(false);
try {
result.set(json.getAsJsonObject().get("product").getAsString().equals("foobar"));
} catch (Exception e) {
}
return result;
}
}
public static void main(String[] args) {
Gson gson = new GsonBuilder().registerTypeAdapter(MyBoolean.class, new MyAdapter()).create();
System.out.println(gson.fromJson("{\"product\": \"foobar\"}", MyBoolean.class).get());
System.out.println(gson.fromJson("{\"product\": \"foobaz\"}", MyBoolean.class).get());
}
}
包io.ram.ram;
导入java.lang.reflect.Type;
导入com.google.gson.gson;
导入com.google.gson.GsonBuilder;
导入com.google.gson.JsonDeserializationContext;
导入com.google.gson.JsonDeserializer;
导入com.google.gson.JsonElement;
导入com.google.gson.JsonParseException;
公共类测试员{
公共静态类MyBoolean{
私有布尔值;
公共无效集(布尔值){
这个值=值;
}
公共布尔get(){
返回值;
}
}
公共静态类MyAdapter实现JsonDeserializer{
公共MyBoolean反序列化(JsonElement json,类型类型,JsonDeserializationContext)
抛出JsonParseException{
MyBoolean结果=新的MyBoolean();
result.set(假);
试一试{
set(json.getAsJsonObject().get(“product”).getAsString().equals(“foobar”));
}捕获(例外e){
}
返回结果;
}
}
公共静态void main(字符串[]args){
Gson Gson=new GsonBuilder().registerTypeAdapter(MyBoolean.class,new MyAdapter()).create();
System.out.println(gson.fromJson(“{\”product\“:\”foobar\“}”,MyBoolean.class.get());
System.out.println(gson.fromJson(“{\”product\“:\”foobaz\“}”,MyBoolean.class.get());
}
}
正如我所说,在为自定义序列化注册类型适配器之后,您可以通过一行代码实现所需的功能。(注意:布尔类是最终类,因此我们无法扩展它。对于此错误信息,我们深表歉意。)
当然,您可以为字符串“product”
和“foobar”
参数化MyAdapter
,因此您不必为每种可能的情况创建此类类。我知道您说过GSON,但jackson提供的基于pojo的方法使您想做的事情非常方便,不必发布:
简单pojo:
public class FooPojo {
@JsonProperty
private String product;
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
public boolean isProductEqualTo(String check) {
return product.equals(check);
}
}
解析和检查:
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
FooPojo fooPojo = objectMapper.readValue("{ \"product\": \"foobar\"}", FooPojo.class);
System.out.println(fooPojo.isProductEqualTo("foobar"));
}
使用流是一种有趣的方法;我希望gson也能有一些方便的方法来实现这一点。实际上,javax.json.JsonObject
有一个getString
方法,如果该值不是String
,则可能会有一个默认值,但显然,谷歌创建了自己的数据模型…;-)注:如果更多的开发人员从“出错时返回null”转向“返回可选”方案,我将表示欢迎。@Smutje AFAIR,JSON处理在Java 7之前就已经引入Java 8及其可选项,而Gson最初是在2008年发布的,大约十年前,所以我认为javax.json的作者只是重新考虑了现有的库,比如Gson或Jackson。返回null
更便宜,但是如果您更喜欢使用OneLiner,那么这种情况下就不太方便了……好吧,这可以解释Java中JSON表示的差异。您是否查看过类似的查询库?我最近在gson
中查找了相同的功能,但没有找到它