1

I want to validate a JSON string by using com.google.gson.JsonParser. By this post, I know that JsonParser.parse() is lenient enough to treat invalid abc as valid "abc". That is to say, JsonParser.parse() will not throw a JsonSyntaxException or JsonParseException for the string below:

abc

By adding the logic of jsonElement.isJsonObject(), the following code can recognize invalid JSON string of abc.

boolean isJSON(String jsonString) {

  try {
    JsonElement jsonElement = new JsonParser().parse(jsonString);

    if (!jsonElement.isJsonObject()) {
      return false;
    }
  } catch (Exception e) {
    return false;
  }

  return true;
}

However, it still cannot recognize invalid JSON format from the following strings.

{"name": mike}

or

{name: mike}

How to recognize invalid JSON for these cases?

Community
  • 1
  • 1
yasi
  • 451
  • 7
  • 18
  • I'm not going to modify 3rd party code, neither am I able to change the input string. I just want to make a strong JSON validation. – yasi Apr 21 '17 at 13:01

1 Answers1

1

You should not use JsonParser for a couple of reasons:

  • It uses lenient JsonReader under the hood.
  • It creates a JSON document view in memory (JsonElement) that is definitely not a way to go for not small documents.

You can use JsonReader safely:

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;
        while ( (token = jsonReader.peek()) != END_DOCUMENT && token != null ) {
            skipToken(jsonReader);
        }
        return true;
    } catch ( final MalformedJsonException ignored ) {
        return false;
    }
}

// Maybe skipToken will be a part of Gson someday: https://github.com/google/gson/issues/1054
private static void skipToken(final JsonReader reader)
        throws IOException {
    final JsonToken token = reader.peek();
    switch ( token ) {
    case BEGIN_ARRAY:
        reader.beginArray();
        break;
    case END_ARRAY:
        reader.endArray();
        break;
    case BEGIN_OBJECT:
        reader.beginObject();
        break;
    case END_OBJECT:
        reader.endObject();
        break;
    case NAME:
        reader.nextName();
        break;
    case STRING:
    case NUMBER:
    case BOOLEAN:
    case NULL:
        reader.skipValue();
        break;
    case END_DOCUMENT:
    default:
        throw new AssertionError(token);
    }
}

Test:

public static void main(final String... args)
        throws IOException {
    System.out.println(isJsonValid("\"abc\""));
    System.out.println(isJsonValid("{\"name\": \"mike\"}"));
    System.out.println(isJsonValid("abc"));
    System.out.println(isJsonValid("{\"name\": mike}"));
    System.out.println(isJsonValid("{name: mike}"));
    System.out.println(isJsonValid("{name: \"mike\"}"));
}

The test above produces:

true
true
false
false
false
false

Lyubomyr Shaydariv
  • 20,327
  • 12
  • 64
  • 105
  • @yasi Hm, I'm not at the desktop at the moment, but the code line you mentioned should print `true` according to the JSON spec, and the test prints the same. Or am I missing something? – Lyubomyr Shaydariv Apr 22 '17 at 08:15
  • I was typing too long. :) – Lyubomyr Shaydariv Apr 22 '17 at 08:17
  • 1
    Yes, the code should print true for "abc", my mistake. However, by reading http://www.json.org/ (the legend on right side of it), I think "abc" is invalid JSON format string since any JSON "object" begins with "{" and ends with "}". However, online JSON validator, http://jsonlint.com/ , validates it's valid JSON string. Please help me out for the confusion. – yasi Apr 22 '17 at 08:34
  • @yasi Please see: http://stackoverflow.com/questions/18419428/what-is-the-minimum-valid-json - it's confusing me though. – Lyubomyr Shaydariv Apr 22 '17 at 09:04