В каком случае Джексон создает ShortNode при десериализации JSON с ObjectMapper.readTree? - PullRequest
0 голосов
/ 05 мая 2018

У меня есть код, который десериализует JSON из InputStream через ObjectMapper Джексона (в основном, как и new ObjectMapper().readTree(...)). Я обнаружил, что он создает либо IntNode, либо LongNode для целых чисел (в зависимости от того, насколько велико число), но я никогда не видел ShortNode с. Мне нужно знать, когда они создаются (если вообще создаются), потому что у меня есть хитрая логика, основанная на типе возврата NumericNode.numberValue(). Я ничего не нашел в документации Джексона, и код Джексона кажется мне не очень понятным.

1 Ответ

0 голосов
/ 08 мая 2018

com.fasterxml.jackson.core.JsonToken enum содержит VALUE_NUMBER_INT с ниже документацией :

VALUE_NUMBER_INT возвращается, когда целочисленный числовой токен встречается в контексте значения: то есть число, которое не имеет маркер с плавающей запятой или экспоненты в нем (состоит только из необязательного знак, за которым следуют одна или несколько цифр)

Существует также токен VALUE_NUMBER_FLOAT, используемый для чисел с плавающей запятой. Также взгляните на com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer#_fromInt метод, который вы можете найти здесь .

protected final JsonNode _fromInt(JsonParser p, DeserializationContext ctxt,
        JsonNodeFactory nodeFactory) throws IOException
{
    JsonParser.NumberType nt;
    int feats = ctxt.getDeserializationFeatures();
    if ((feats & F_MASK_INT_COERCIONS) != 0) {
        if (DeserializationFeature.USE_BIG_INTEGER_FOR_INTS.enabledIn(feats)) {
            nt = JsonParser.NumberType.BIG_INTEGER;
        } else if (DeserializationFeature.USE_LONG_FOR_INTS.enabledIn(feats)) {
            nt = JsonParser.NumberType.LONG;
        } else {
            nt = p.getNumberType();
        }
    } else {
        nt = p.getNumberType();
    }
    if (nt == JsonParser.NumberType.INT) {
        return nodeFactory.numberNode(p.getIntValue());
    }
    if (nt == JsonParser.NumberType.LONG) {
        return nodeFactory.numberNode(p.getLongValue());
    }
    return nodeFactory.numberNode(p.getBigIntegerValue());
}

Также вы должны взглянуть на com.fasterxml.jackson.core.base.ParserBase#_parseNumericValue метод, который вы можете найти здесь

/**
 * Method that will parse actual numeric value out of a syntactically
 * valid number value. Type it will parse into depends on whether
 * it is a floating point number, as well as its magnitude: smallest
 * legal type (of ones available) is used for efficiency.
 *
 * @param expType Numeric type that we will immediately need, if any;
 *   mostly necessary to optimize handling of floating point numbers
 */
protected void _parseNumericValue(int expType) throws IOException
{
    // Int or float?
    if (_currToken == JsonToken.VALUE_NUMBER_INT) {
        int len = _intLength;
        // First: optimization for simple int
        if (len <= 9) { 
            int i = _textBuffer.contentsAsInt(_numberNegative);
            _numberInt = i;
            _numTypesValid = NR_INT;
            return;
        }
        if (len <= 18) { // definitely fits AND is easy to parse using 2 int parse calls
            long l = _textBuffer.contentsAsLong(_numberNegative);
            // Might still fit in int, need to check
            if (len == 10) {
                if (_numberNegative) {
                    if (l >= MIN_INT_L) {
                        _numberInt = (int) l;
                        _numTypesValid = NR_INT;
                        return;
                    }
                } else {
                    if (l <= MAX_INT_L) {
                        _numberInt = (int) l;
                        _numTypesValid = NR_INT;
                        return;
                    }
                }
            }
            _numberLong = l;
            _numTypesValid = NR_LONG;
            return;
        }
        _parseSlowInt(expType);
        return;
    }
    if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) {
        _parseSlowFloat(expType);
        return;
    }
    _reportError("Current token (%s) not numeric, can not use numeric value accessors", _currToken);
}

Как видите, во время десериализации нет типов short или Short. Вы должны избегать создания логики для типа значения, которое создается внешней библиотекой. В этом случае невозможно принудительно использовать Short.

EDIT
И, конечно, это невозможно, поскольку спецификация JSON не поддерживает это. Посмотрите ссылки ниже для получения более подробной информации:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...