如何使用GSON检查JSON在Java中是否有效?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用GSON检查JSON在Java中是否有效?相关的知识,希望对你有一定的参考价值。

我有方法必须检查JSON是否有效,在How to check whether a given string is valid JSON in Java上找到但它不起作用。

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

它给了我true,和

System.out.println(renderHtml.isJson("bncjbhjfjhj"));

也给了我true

答案

虽然这对你来说可能很奇怪

"bncjbhjfjhj"

确实是有效的json,因为它是一个字符串,它是唯一的字符串。

根据不那么新的JSON RFC

JSON文本是序列化值。请注意,某些先前的JSON规范将JSON文本约束为对象或数组。只生成调用JSON文本的对象或数组的实现将是可互操作的,因为所有实现都将接受这些作为符合JSON文本。

另一答案

你不应该使用Gson进行这样的验证:

  • Gson是一个执行反序列化的对象,因此它将整个JSON反序列化为内存中的对象。
  • Gson,我不知道它,对于一些无效的JSON可能不是很严格:bncjbhjfjhj被反序列化为java.lang.String实例。惊喜,惊喜!
private static final Gson gson = new Gson();

private static final String VALID_JSON = "{"status": "UP"}";
private static final String INVALID_JSON = "bncjbhjfjhj";

System.out.println(gson.fromJson(VALID_JSON, Object.class).getClass());
System.out.println(gson.fromJson(INVALID_JSON, Object.class).getClass());

输出:

com.google.gson.internal.LinkedTreeMap类 class java.lang.String

你可以在这里做的是使用JsonReader通过令牌读取传入的JSON令牌,从而使得给定的JSON文档在语法上是有效的。

private static boolean isJsonValid(final String json)
        throws IOException {
    return isJsonValid(new StringReader(json));
}

private static boolean isJsonValid(final Reader reader)
        throws IOException {
    return isJsonValid(new JsonReader(reader));
}

private static boolean isJsonValid(final JsonReader jsonReader)
        throws IOException {
    try {
        JsonToken token;
        loop:
        while ( (token = jsonReader.peek()) != END_DOCUMENT && token != null ) {
            switch ( token ) {
            case BEGIN_ARRAY:
                jsonReader.beginArray();
                break;
            case END_ARRAY:
                jsonReader.endArray();
                break;
            case BEGIN_OBJECT:
                jsonReader.beginObject();
                break;
            case END_OBJECT:
                jsonReader.endObject();
                break;
            case NAME:
                jsonReader.nextName();
                break;
            case STRING:
            case NUMBER:
            case BOOLEAN:
            case NULL:
                jsonReader.skipValue();
                break;
            case END_DOCUMENT:
                break loop;
            default:
                throw new AssertionError(token);
            }
        }
        return true;
    } catch ( final MalformedJsonException ignored ) {
        return false;
    }
}

然后测试一下:

System.out.println(isJsonValid(VALID_JSON));
System.out.println(isJsonValid(INVALID_JSON));

输出:

真正 假

另一答案

根据org.json,我找到了解决方案,但使用了How to check whether a given string is valid JSON in Java

public static boolean isJson(String Json) {
        try {
            new JSONObject(Json);
        } catch (JSONException ex) {
            try {
                new JSONArray(Json);
            } catch (JSONException ex1) {
                return false;
            }
        }
        return true;
    }

现在随机看字符串bncjbhjfjhjfalse{"status": "UP"}是真的。

另一答案

另一种选择是将自定义的后检查应用到顶级json对象,如下所示:

import org.junit.Test;
import com.google.gson.*;
import static org.junit.Assert.*;

public class JsonTest {

    private JsonObject parse(@Nonnull String json) throws JsonSyntaxException {
        JsonElement res = new JsonParser().parse(json);
        System.out.println(res);
        if (!res.isJsonObject()) {
            throw new JsonSyntaxException("Top level JSON object required");
        }
        return res.getAsJsonObject();
    }

    private static void assertThrows(Runnable r) {
        try {
            r.run();
            fail();
        } catch (JsonSyntaxException expected) {
            // ok
        }
    }

    @Test
    public void testIt() {
        assertThrows(() -> parse(""));
        assertThrows(() -> parse("null"));
        assertThrows(() -> parse("Abracadabra"));
        assertThrows(() -> parse("[]"));
        assertTrue(parse("{}").entrySet().isEmpty());
        assertThrows(() -> parse("{a: }"));
        assertThrows(() -> parse("{a: ,}"));
        assertThrows(() -> parse("{a: 0,}"));
        assertTrue(parse("{a: null}").get("a").isJsonNull());
        assertEquals(0, parse("{a: 0}").get("a").getAsInt());
        assertEquals("", parse("{a: ''}").get("a").getAsString());
        assertEquals("", parse("{a: ""}").get("a").getAsString());
        assertEquals(0, parse("{a: []}").get("a").getAsJsonArray().size());
        //assertThrows(() -> parse("{a: [1,]}")); // TODO: this parses without error to {"a":[1,null]}
    }

}

以上是关于如何使用GSON检查JSON在Java中是否有效?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用带有 Kotlin 的 Gson 库访问 JSON 有效负载中的嵌套值

如何在java中使用gson解码json字符串?

如何检查传递的对象是否是MarkLogic中的有效JSON?

如何在 Python 中检查字符串是不是是有效的 JSON?

如何将Java对象转换为JSON(Gson)?

如何使用 GSON 或 Java 中的其他 JSON 库反序列化列表?