bson/src/main/org/bson/json/JsonReader.java
@Override
    public BsonType readBsonType() {
        if (isClosed()) {
            throw new IllegalStateException("This instance has been closed");
        }
        if (getState() == State.INITIAL || getState() == State.DONE || getState() == State.SCOPE_DOCUMENT) {
            // in JSON the top level value can be of any type so fall through
            setState(State.TYPE);
        }
        if (getState() != State.TYPE) {
            throwInvalidState("readBSONType", State.TYPE);
        }

        if (getContext().getContextType() == BsonContextType.DOCUMENT) {
            JsonToken nameToken = popToken();
            switch (nameToken.getType()) {
                case STRING:
                case UNQUOTED_STRING:
                    setCurrentName(nameToken.getValue(String.class));
                    break;
                case END_OBJECT:
                    setState(State.END_OF_DOCUMENT);
                    return BsonType.END_OF_DOCUMENT;
                default:
                    throw new JsonParseException("JSON reader was expecting a name but found '%s'.", nameToken.getValue());
            }

            JsonToken colonToken = popToken();
            if (colonToken.getType() != JsonTokenType.COLON) {
                throw new JsonParseException("JSON reader was expecting ':' but found '%s'.", colonToken.getValue());
            }
        }

        JsonToken token = popToken();
        if (getContext().getContextType() == BsonContextType.ARRAY && token.getType() == JsonTokenType.END_ARRAY) {
            setState(State.END_OF_ARRAY);
            return BsonType.END_OF_DOCUMENT;
        }

        boolean noValueFound = false;
        switch (token.getType()) {
            case BEGIN_ARRAY:
                setCurrentBsonType(BsonType.ARRAY);
                break;
            case BEGIN_OBJECT:
                visitExtendedJSON();
                break;
            case DOUBLE:
                setCurrentBsonType(BsonType.DOUBLE);
                currentValue = token.getValue();
                break;
            case END_OF_FILE:
                setCurrentBsonType(BsonType.END_OF_DOCUMENT);
                break;
            case INT32:
                setCurrentBsonType(BsonType.INT32);
                currentValue = token.getValue();
                break;
            case INT64:
                setCurrentBsonType(BsonType.INT64);
                currentValue = token.getValue();
                break;
            case REGULAR_EXPRESSION:
                setCurrentBsonType(BsonType.REGULAR_EXPRESSION);
                currentValue = token.getValue();
                break;
            case STRING:
                setCurrentBsonType(BsonType.STRING);
                currentValue = token.getValue();
                break;
            case UNQUOTED_STRING:
                String value = token.getValue(String.class);

                if ("false".equals(value) || "true".equals(value)) {
                    setCurrentBsonType(BsonType.BOOLEAN);
                    currentValue = Boolean.parseBoolean(value);
                } else if ("Infinity".equals(value)) {
                    setCurrentBsonType(BsonType.DOUBLE);
                    currentValue = Double.POSITIVE_INFINITY;
                } else if ("NaN".equals(value)) {
                    setCurrentBsonType(BsonType.DOUBLE);
                    currentValue = Double.NaN;
                } else if ("null".equals(value)) {
                    setCurrentBsonType(BsonType.NULL);
                } else if ("undefined".equals(value)) {
                    setCurrentBsonType(BsonType.UNDEFINED);
                } else if ("MinKey".equals(value)) {
                    visitEmptyConstructor();
                    setCurrentBsonType(BsonType.MIN_KEY);
                    currentValue = new MinKey();
                } else if ("MaxKey".equals(value)) {
                    visitEmptyConstructor();
                    setCurrentBsonType(BsonType.MAX_KEY);
                    currentValue = new MaxKey();
                } else if ("BinData".equals(value)) {
                    setCurrentBsonType(BsonType.BINARY);
                    currentValue = visitBinDataConstructor();
                } else if ("Date".equals(value)) {
                    currentValue = visitDateTimeConstructorWithOutNew();
                    setCurrentBsonType(BsonType.STRING);
                } else if ("HexData".equals(value)) {
                    setCurrentBsonType(BsonType.BINARY);
                    currentValue = visitHexDataConstructor();
                } else if ("ISODate".equals(value)) {
                    setCurrentBsonType(BsonType.DATE_TIME);
                    currentValue = visitISODateTimeConstructor();
                } else if ("NumberInt".equals(value)) {
                    setCurrentBsonType(BsonType.INT32);
                    currentValue = visitNumberIntConstructor();
                } else if ("NumberLong".equals(value)) {
                    setCurrentBsonType(BsonType.INT64);
                    currentValue = visitNumberLongConstructor();
                } else if ("NumberDecimal".equals(value)) {
                    setCurrentBsonType(BsonType.DECIMAL128);
                    currentValue = visitNumberDecimalConstructor();
                } else if ("ObjectId".equals(value)) {
                    setCurrentBsonType(BsonType.OBJECT_ID);
                    currentValue = visitObjectIdConstructor();
                } else if ("Timestamp".equals(value)) {
                    setCurrentBsonType(BsonType.TIMESTAMP);
                    currentValue = visitTimestampConstructor();
                } else if ("RegExp".equals(value)) {
                    setCurrentBsonType(BsonType.REGULAR_EXPRESSION);
                    currentValue = visitRegularExpressionConstructor();
                } else if ("DBPointer".equals(value)) {
                    setCurrentBsonType(BsonType.DB_POINTER);
                    currentValue = visitDBPointerConstructor();
                } else if ("UUID".equals(value)
                           || "GUID".equals(value)
                           || "CSUUID".equals(value)
                           || "CSGUID".equals(value)
                           || "JUUID".equals(value)
                           || "JGUID".equals(value)
                           || "PYUUID".equals(value)
                           || "PYGUID".equals(value)) {
                    setCurrentBsonType(BsonType.BINARY);
                    currentValue = visitUUIDConstructor(value);
                } else if ("new".equals(value)) {
                    visitNew();
                } else {
                    noValueFound = true;
                }
                break;
            default:
                noValueFound = true;
                break;
        }
        if (noValueFound) {
            throw new JsonParseException("JSON reader was expecting a value but found '%s'.", token.getValue());
        }

        if (getContext().getContextType() == BsonContextType.ARRAY || getContext().getContextType() == BsonContextType.DOCUMENT) {
            JsonToken commaToken = popToken();
            if (commaToken.getType() != JsonTokenType.COMMA) {
                pushToken(commaToken);
            }
        }

        switch (getContext().getContextType()) {
            case DOCUMENT:
            case SCOPE_DOCUMENT:
            default:
                setState(State.NAME);
                break;
            case ARRAY:
            case JAVASCRIPT_WITH_SCOPE:
            case TOP_LEVEL:
                setState(State.VALUE);
                break;
        }
        return getCurrentBsonType();
    }
@Override
    public BsonType readBsonType() {
        if (isClosed()) {
            throw new IllegalStateException("This instance has been closed");
        }
        if (getState() == State.INITIAL || getState() == State.DONE || getState() == State.SCOPE_DOCUMENT) {
            // in JSON the top level value can be of any type so fall through
            setState(State.TYPE);
        }
        if (getState() != State.TYPE) {
            throwInvalidState("readBSONType", State.TYPE);
        }

        if (getContext().getContextType() == BsonContextType.DOCUMENT) {
            JsonToken nameToken = popToken();
            switch (nameToken.getType()) {
                case STRING:
                case UNQUOTED_STRING:
                    setCurrentName(nameToken.getValue(String.class));
                    break;
                case END_OBJECT:
                    setState(State.END_OF_DOCUMENT);
                    return BsonType.END_OF_DOCUMENT;
                default:
                    throw new JsonParseException("JSON reader was expecting a name but found '%s'.", nameToken.getValue());
            }

            JsonToken colonToken = popToken();
            if (colonToken.getType() != JsonTokenType.COLON) {
                throw new JsonParseException("JSON reader was expecting ':' but found '%s'.", colonToken.getValue());
            }
        }

        JsonToken token = popToken();
        if (getContext().getContextType() == BsonContextType.ARRAY && token.getType() == JsonTokenType.END_ARRAY) {
            setState(State.END_OF_ARRAY);
            return BsonType.END_OF_DOCUMENT;
        }

        boolean noValueFound = false;
        switch (token.getType()) {
            case BEGIN_ARRAY:
                setCurrentBsonType(BsonType.ARRAY);
                break;
            case BEGIN_OBJECT:
                visitExtendedJSON();
                break;
            case DOUBLE:
                setCurrentBsonType(BsonType.DOUBLE);
                currentValue = token.getValue();
                break;
            case END_OF_FILE:
                setCurrentBsonType(BsonType.END_OF_DOCUMENT);
                break;
            case INT32:
                setCurrentBsonType(BsonType.INT32);
                currentValue = token.getValue();
                break;
            case INT64:
                setCurrentBsonType(BsonType.INT64);
                currentValue = token.getValue();
                break;
            case REGULAR_EXPRESSION:
                setCurrentBsonType(BsonType.REGULAR_EXPRESSION);
                currentValue = token.getValue();
                break;
            case STRING:
                setCurrentBsonType(BsonType.STRING);
                currentValue = token.getValue();
                break;
            case UNQUOTED_STRING:
                String value = token.getValue(String.class);

                if ("false".equals(value) || "true".equals(value)) {
                    setCurrentBsonType(BsonType.BOOLEAN);
                    currentValue = Boolean.parseBoolean(value);
                } else if ("Infinity".equals(value)) {
                    setCurrentBsonType(BsonType.DOUBLE);
                    currentValue = Double.POSITIVE_INFINITY;
                } else if ("NaN".equals(value)) {
                    setCurrentBsonType(BsonType.DOUBLE);
                    currentValue = Double.NaN;
                } else if ("null".equals(value)) {
                    setCurrentBsonType(BsonType.NULL);
                } else if ("undefined".equals(value)) {
                    setCurrentBsonType(BsonType.UNDEFINED);
                } else if ("MinKey".equals(value)) {
                    visitEmptyConstructor();
                    setCurrentBsonType(BsonType.MIN_KEY);
                    currentValue = new MinKey();
                } else if ("MaxKey".equals(value)) {
                    visitEmptyConstructor();
                    setCurrentBsonType(BsonType.MAX_KEY);
                    currentValue = new MaxKey();
                } else if ("BinData".equals(value)) {
                    setCurrentBsonType(BsonType.BINARY);
                    currentValue = visitBinDataConstructor();
                } else if ("Date".equals(value)) {
                    currentValue = visitDateTimeConstructorWithOutNew();
                    setCurrentBsonType(BsonType.STRING);
                } else if ("HexData".equals(value)) {
                    setCurrentBsonType(BsonType.BINARY);
                    currentValue = visitHexDataConstructor();
                } else if ("ISODate".equals(value)) {
                    setCurrentBsonType(BsonType.DATE_TIME);
                    currentValue = visitISODateTimeConstructor();
                } else if ("NumberInt".equals(value)) {
                    setCurrentBsonType(BsonType.INT32);
                    currentValue = visitNumberIntConstructor();
                } else if ("NumberLong".equals(value)) {
                    setCurrentBsonType(BsonType.INT64);
                    currentValue = visitNumberLongConstructor();
                } else if ("NumberDecimal".equals(value)) {
                    setCurrentBsonType(BsonType.DECIMAL128);
                    currentValue = visitNumberDecimalConstructor();
                } else if ("ObjectId".equals(value)) {
                    setCurrentBsonType(BsonType.OBJECT_ID);
                    currentValue = visitObjectIdConstructor();
                } else if ("Timestamp".equals(value)) {
                    setCurrentBsonType(BsonType.TIMESTAMP);
                    currentValue = visitTimestampConstructor();
                } else if ("RegExp".equals(value)) {
                    setCurrentBsonType(BsonType.REGULAR_EXPRESSION);
                    currentValue = visitRegularExpressionConstructor();
                } else if ("DBPointer".equals(value)) {
                    setCurrentBsonType(BsonType.DB_POINTER);
                    currentValue = visitDBPointerConstructor();
                } else if ("UUID".equals(value)
                           || "GUID".equals(value)
                           || "CSUUID".equals(value)
                           || "CSGUID".equals(value)
                           || "JUUID".equals(value)
                           || "JGUID".equals(value)
                           || "PYUUID".equals(value)
                           || "PYGUID".equals(value)) {
                    setCurrentBsonType(BsonType.BINARY);
                    currentValue = visitUUIDConstructor(value);
                } else if ("new".equals(value)) {
                    visitNew();
                } else {
                    noValueFound = true;
                }
                break;
            default:
                noValueFound = true;
                break;
        }
        if (noValueFound) {
            throw new JsonParseException("JSON reader was expecting a value but found '%s'.", token.getValue());
        }

        if (getContext().getContextType() == BsonContextType.ARRAY || getContext().getContextType() == BsonContextType.DOCUMENT) {
            JsonToken commaToken = popToken();
            if (commaToken.getType() != JsonTokenType.COMMA) {
                pushToken(commaToken);
            }
        }

        switch (getContext().getContextType()) {
            case DOCUMENT:
            case SCOPE_DOCUMENT:
            default:
                setState(State.NAME);
                break;
            case ARRAY:
            case JAVASCRIPT_WITH_SCOPE:
            case TOP_LEVEL:
                setState(State.VALUE);
                break;
        }
        return getCurrentBsonType();
    }
CHECKSTYLE:OFF