如何使用GSON检查JSON在Java中是否有效?
我有一个必须检查JSON是否有效的方法,可以在上找到,但它不起作用如何使用GSON检查JSON在Java中是否有效?,java,json,gson,Java,Json,Gson,我有一个必须检查JSON是否有效的方法,可以在上找到,但它不起作用 public static boolean isJson(String Json) { Gson gson = new Gson(); try { gson.fromJson(Json, Object.class); return true; } catch (com.google.gson.JsonSyntaxException e
public static boolean isJson(String Json) {
Gson gson = new Gson();
try {
gson.fromJson(Json, Object.class);
return true;
} catch (com.google.gson.JsonSyntaxException ex) {
return false;
}
}
如果我对某个字符串使用这个方法,它总是返回true。例如:
System.out.println(renderHtml.isJson("{\"status\": \"UP\"}"));
它给了我正确的,并且
System.out.println(renderHtml.isJson("bncjbhjfjhj"));
也给了我真的
。虽然你可能觉得奇怪
"bncjbhjfjhj"
确实是有效的json,因为它是一个字符串,并且是唯一的字符串
根据这项研究,这并不新鲜
JSON文本是一个序列化的值。请注意,某些以前的
JSON规范将JSON文本约束为对象或
数组。仅生成对象或数组的实现,其中
所调用的JSON文本将是可互操作的,因为所有
实现将接受这些作为一致的JSON文本
您不应使用Gson
进行此类验证:
Gson
是一个执行反序列化的对象,因此它将整个JSON反序列化为内存中的一个对象
Gson
,我不知道,对于一些无效的JSON可能不是很严格:bncjbhjfjhj
被反序列化为java.lang.String
实例。惊喜李>
private static final Gson Gson=new Gson();
私有静态最终字符串有效\u JSON=“{\”状态\“:\”向上\“}”;
私有静态最终字符串无效\u JSON=“bncjbhjfjhj”;
System.out.println(gson.fromJson(有效的_JSON,Object.class).getClass());
System.out.println(gson.fromJson(无效的_JSON,Object.class).getClass());
输出:
class com.google.gson.internal.LinkedTreeMap
类java.lang.String
您可以在这里使用JsonReader
逐个令牌读取传入的JSON令牌,从而确定给定的JSON文档在语法上是否有效
private静态布尔值isJsonValid(最终字符串json)
抛出IOException{
返回isJsonValid(新的StringReader(json));
}
私有静态布尔值isJsonValid(最终读取器)
抛出IOException{
返回isJsonValid(新的JsonReader(reader));
}
私有静态布尔值isJsonValid(最终JsonReader JsonReader)
抛出IOException{
试一试{
杰森托肯代币;
循环:
while((token=jsonReader.peek())!=END\u文档和&token!=null){
交换机(令牌){
案例开始\u数组:
jsonReader.beginArray();
打破
案例结束单元阵列:
jsonReader.endArray();
打破
案例开始对象:
jsonReader.beginObject();
打破
案例结束对象:
jsonReader.endObject();
打破
案例名称:
jsonReader.nextName();
打破
大小写字符串:
案件编号:
大小写布尔值:
大小写为空:
jsonReader.skipValue();
打破
案例结束文件:
断环;
违约:
抛出新断言错误(令牌);
}
}
返回true;
}捕获(忽略最终格式错误的JSONException){
返回false;
}
}
然后测试它:
System.out.println(isJsonValid(VALID_JSON));
System.out.println(isJsonValid(INVALID_JSON));
输出:
正确
假的
我找到了解决方案,但使用了org.json
库,根据
现在随机字符串bncjbhjfjjj
是false
和{“status”:“UP”}
是true。我很惊讶
默认情况下,Gson是严格的,只接受由指定的JSON。这个选项使解析器在接受什么方面变得自由
这似乎是彻头彻尾的谎言,因为它实际上总是宽大的。而且,即使是任何对的呼吁都被完全忽略了
在“由于遗留兼容性原因”进行了一些浏览和请求之后,我终于找到了合理的解决方法:
杰克·沃顿于2017年12月15日发表评论
您可以调用getAdapter(type).fromJson(gson.newJsonReader(input))
而不仅仅是从JSON(输入)获得严格的解析。我们应该
真的不推荐所有fromJson方法并添加新版本
默认情况下是严格的
原因是很久以前的错误决定,我们无法再改变;(
因此,这里有一个纯Gson解决方案,用于使用大量测试用例进行严格的json对象解析
import org.junit.Test;
import com.google.gson.*;
import com.google.gson.stream.JsonReader;
import static org.junit.Assert.*;
public class JsonTest {
private static final TypeAdapter<JsonObject> strictGsonObjectAdapter =
new Gson().getAdapter(JsonObject.class);
public static JsonObject parseStrict(String json) {
// https://stackoverflow.com/questions/43233898/how-to-check-if-json-is-valid-in-java-using-gson/47890960#47890960
try {
//return strictGsonObjectAdapter.fromJson(json); // this still allows multiple top level values (
try (JsonReader reader = new JsonReader(new StringReader(json))) {
JsonObject result = strictGsonObjectAdapter.read(reader);
reader.hasNext(); // throws on multiple top level values
return result;
}
} catch (IOException e) {
throw new JsonSyntaxException(e);
}
}
@Test
public void testStrictParsing() {
// https://static.javadoc.io/com.google.code.gson/gson/2.8.5/com/google/gson/stream/JsonReader.html#setLenient-boolean-
// Streams that start with the non-execute prefix, ")]}'\n".
assertThrows(JsonSyntaxException.class, () -> parseStrict("){}"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("]{}"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("}{}"));
// Streams that include multiple top-level values. With strict parsing, each stream must contain exactly one top-level value.
assertThrows(JsonSyntaxException.class, () -> parseStrict("{}{}"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("{}[]null"));
// Top-level values of any type. With strict parsing, the top-level value must be an object or an array.
assertThrows(JsonSyntaxException.class, () -> parseStrict(""));
assertThrows(JsonSyntaxException.class, () -> parseStrict("null"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("Abracadabra"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("13"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("\"literal\""));
assertThrows(JsonSyntaxException.class, () -> parseStrict("[]"));
// Numbers may be NaNs or infinities.
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"number\": NaN}"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"number\": Infinity}"));
// End of line comments starting with // or # and ending with a newline character.
assertThrows(JsonSyntaxException.class, () -> parseStrict("{//comment\n}"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("{#comment\n}"));
// C-style comments starting with /* and ending with */. Such comments may not be nested.
assertThrows(JsonSyntaxException.class, () -> parseStrict("{/*comment*/}"));
// Names that are unquoted or 'single quoted'.
assertThrows(JsonSyntaxException.class, () -> parseStrict("{a: 1}"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("{'a': 1}"));
// Strings that are unquoted or 'single quoted'.
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"a\": str}"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"a\": ''}"));
// Array elements separated by ; instead of ,.
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"a\": [1;2]}"));
// Unnecessary array separators. These are interpreted as if null was the omitted value.
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"a\": [1,]}"));
// Names and values separated by = or => instead of :.
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"a\" = 13}"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"a\" => 13}"));
// Name/value pairs separated by ; instead of ,.
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"a\": 1; \"b\": 2}"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"a\": }"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"a\": ,}"));
assertThrows(JsonSyntaxException.class, () -> parseStrict("{\"a\": 0,}"));
assertTrue(parseStrict("{} ").entrySet().isEmpty());
assertTrue(parseStrict("{\"a\": null} \n \n").get("a").isJsonNull());
assertEquals(0, parseStrict("{\"a\": 0}").get("a").getAsInt());
assertEquals("", parseStrict("{\"a\": \"\"}").get("a").getAsString());
assertEquals(0, parseStrict("{\"a\": []}").get("a").getAsJsonArray().size());
}
}
这对我有用
public static boolean isJson(String Json) {
Gson gson = new Gson();
try {
gson.fromJson(Json, Object.class);
Object jsonObjType = gson.fromJson(Json, Object.class).getClass();
if(jsonObjType.equals(String.class)){
return false;
}
return true;
} catch (com.google.gson.JsonSyntaxException ex) {
return false;
}
}
你在寻找模式验证吗?尽管你在这一点上是正确的,OP实际上是在问为什么Gson
没有拒绝bncjbjfjhj
(没有引号)作为无效的JSON文档。因为它是有效的JSON?它只是一个简单的字符串OP用renderHtml.isJson(“bncjbjfjhj”)测试它
,而不是使用renderHtml.isJson(“\'bncjbhjfjj\”)
@WilomGfx你说得对。我通过使用org.json
库找到了解决方案。@WilomGfx因为Gson
与更低级的Gson组件JsonReader
的工作原理不同。请同时检查bncjbhjbhjfjjjjj
和“bncjbhjfjfjfjj”
使用任何JSON linter。您希望使用此方法验证的最大JSON的大小是多少?不是很大。它用于从Springboot应用程序读取健康检查。3或4个嵌套级别。它们有一个特殊的JsonParser用于此:虽然此代码片段可能是解决方案,但确实有助于提高帖子的质量。记住您将为将来的读者回答这个问题,而这些人可能不知道您的代码建议的原因。
// https://github.com/google/gson/issues/1208
private static final TypeAdapter<Pojo> strictGsonAdapter = new Gson().getAdapter(Pojo.class);
public static Pojo parsePayment(String json) throws IOException {
return strictGsonAdapter.fromJson(json);
}
public static boolean isJson(String Json) {
Gson gson = new Gson();
try {
gson.fromJson(Json, Object.class);
Object jsonObjType = gson.fromJson(Json, Object.class).getClass();
if(jsonObjType.equals(String.class)){
return false;
}
return true;
} catch (com.google.gson.JsonSyntaxException ex) {
return false;
}
}