gtgaxiola
gtgaxiola

Reputation: 9331

Jackson's JSON (2.5.0) validation not working as expected

Simple test case:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public static void main(String[] args) throws Exception {
    String json = "1,2";
    ObjectMapper parser = new ObjectMapper();
    JsonNode rootNode = parser.readTree(json);

}

Throws the exception:

Exception in thread "main" com.fasterxml.jackson.core.JsonParseException: 
Unexpected character (',' (code 44)): Expected space separating root-level values
at [Source: 1,2; line: 1, column: 3]

All good and dandy, but if I change String json to any of the following:

String json = "null,false";
String json = "[1,2,3,null,\"hello\"],false";
String json = "true,3";
String json = "true,{\"test\":3}";

There is no Exception thrown.

Why the discrepancy?

Upvotes: 3

Views: 9435

Answers (1)

vtor
vtor

Reputation: 9309

By default, Jackson uses ReaderBasedJsonParser, where, when reading/initing JSON to be parsed, there is an explicit check

switch (i) {
        case '"':
            _tokenIncomplete = true;
            t = JsonToken.VALUE_STRING;
            break;
        case '[':
            if (!inObject) {
                _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol);
            }
            t = JsonToken.START_ARRAY;
            break;
        case '{':
            if (!inObject) {
                _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol);
            }
            t = JsonToken.START_OBJECT;
            break;
        case ']':
        case '}':
            // Error: neither is valid at this point; valid closers have
            // been handled earlier
            _reportUnexpectedChar(i, "expected a value");
        case 't':
            _matchTrue();
            t = JsonToken.VALUE_TRUE;
            break;
        case 'f':
            _matchFalse();
            t = JsonToken.VALUE_FALSE;
            break;
        case 'n':
            _matchNull();
            t = JsonToken.VALUE_NULL;
            break;

        case '-':
            /* Should we have separate handling for plus? Although
             * it is not allowed per se, it may be erroneously used,
             * and could be indicate by a more specific error message.
             */
            t = _parseNegNumber();
            break;
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            t = _parsePosNumber(i);
            break;

From the code above you can see that it checks the characters you mentioned - null, true, {, [, false, etc. And in case of any match it returns valid json token. Thats why, if you change

String json = "true,3";

to

String json = "3,true";

It will again throw well known exception.

Note that there is also a check for a given string starting with letter "n", verifying that it is matched with null (same checks for strings starting with "t", "f").

And then interesting is _parsePosNumber(i) method, which basically calls _reportMissingRootWS to check the root - and it fails obviously.

So basically if json is valid it never reaches the "failer" case, or if given string starts with on of those "true", "false", "null", "[", "{", "]", "}" it would be considered as valid json as well.

I would assume that this functionality is in a list of Jackson non standard features, so that the above mentioned formats are considered as valid JSON.

Upvotes: 5

Related Questions