Как Джексон решает, какой тип NumericNode создать из числового значения - PullRequest
0 голосов
/ 12 апреля 2019

В моей строке JSON у меня есть ключ с именем price, когда я строю JsonNode из строки JSON, используя mapper.readTree(string), числовое значение цены преобразуется в NumericNode.Иногда это DoubleNode или FloatNode или IntNode и т. Д. Я понимаю, что на основе типа данных он создает соответствующий узел, но существует ли какая-то особая последовательность, которой он следует для создания узла.Например: пытается создать IntNode, а в случае неудачи пытается создать LongNode?

строку JSON: -

{
  "price":1,
  "price1":1234,
  "price2":2224322343,
  "price3":123.43,
  "price4":1231231212.43
}

1 Ответ

0 голосов
/ 12 апреля 2019

Чтобы найти и ответить, нам нужно взглянуть на внутреннюю реализацию. Мы можем начать с com.fasterxml.jackson.databind.deser.std.NumberDeserializers.NumberDeserializer класса, который содержит код ниже:

switch (p.getCurrentTokenId()) {
case JsonTokenId.ID_NUMBER_INT:
    if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) {
        return _coerceIntegral(p, ctxt);
    }
    return p.getNumberValue();

case JsonTokenId.ID_NUMBER_FLOAT:
    if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
        // 10-Mar-2017, tatu: NaN and BigDecimal won't mix...
        if (!p.isNaN()) {
            return p.getDecimalValue();
        }
    }
    return p.getNumberValue();

getNumberValue метод взят из com.fasterxml.jackson.core.base.ParserBase абстрактного класса и реализован следующим образом:

public Number getNumberValue() throws IOException
{
    if (_numTypesValid == NR_UNKNOWN) {
        _parseNumericValue(NR_UNKNOWN); // will also check event type
    }
    // Separate types for int types
    if (_currToken == JsonToken.VALUE_NUMBER_INT) {
        if ((_numTypesValid & NR_INT) != 0) {
            return _numberInt;
        }
        if ((_numTypesValid & NR_LONG) != 0) {
            return _numberLong;
        }
        if ((_numTypesValid & NR_BIGINT) != 0) {
            return _numberBigInt;
        }
        // Shouldn't get this far but if we do
        return _numberBigDecimal;
    }

    /* And then floating point types. But here optimal type
     * needs to be big decimal, to avoid losing any data?
     */
    if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
        return _numberBigDecimal;
    }
    if ((_numTypesValid & NR_DOUBLE) == 0) { // sanity check
        _throwInternal();
    }
    return _numberDouble;
}

Я проверил реализацию для версии 2.9.8. Для вашей версии это может быть немного иначе.

...