关于fastjson和jackson将json字符串解析成实体的过程(二)

把刚才那些报错的例子,用jackson处理,会发现全部成功,不会报错,测试例子:

关于fastjson和jackson将json字符串解析成实体的过程(二)

关于fastjson和jackson将json字符串解析成实体的过程(二)

关于fastjson和jackson将json字符串解析成实体的过程(二)

那现在看看jackson怎么处理的,进入readValue方法:

关于fastjson和jackson将json字符串解析成实体的过程(二)

进入_jsonFactory.createJsonParser(content):

关于fastjson和jackson将json字符串解析成实体的过程(二)

其实就是根据json字符串转换成一个流,并生成一个jsonParser:

关于fastjson和jackson将json字符串解析成实体的过程(二)

而TypeFactory.type(valueType)方法会生成一个jackson的simple type,例子里是person.class,具体截图:

关于fastjson和jackson将json字符串解析成实体的过程(二)

关于fastjson和jackson将json字符串解析成实体的过程(二)关于fastjson和jackson将json字符串解析成实体的过程(二)

然后进入_readMapAndClose方法:

关于fastjson和jackson将json字符串解析成实体的过程(二)

具体看

DeserializationConfig cfg = copyDeserializationConfig();
DeserializationContext ctxt = _createDeserializationContext(jp, cfg);
result = _findRootDeserializer(cfg, valueType).deserialize(jp, ctxt);

这三行代码。1是拷贝了反序列化的配置,2是根据配置和上面的ReaderBasedParser,生成一个反序列化的上下文对象,3是先根据配置和所传的对象类型找到对应的反序列化器,感觉这里的逻辑和fastjson很像:

关于fastjson和jackson将json字符串解析成实体的过程(二)

然后具体解析就是deserialize方法了:

public final Object deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException, JsonProcessingException
    {
        JsonToken t = jp.getCurrentToken();
        if(t == JsonToken.START_OBJECT)
        {
            jp.nextToken();
            return deserializeFromObject(jp, ctxt);
        }
        static class _cls1
        {

            static final int $SwitchMap$org$codehaus$jackson$JsonToken[];
            static final int $SwitchMap$org$codehaus$jackson$JsonParser$NumberType[];

            static 
            {
                $SwitchMap$org$codehaus$jackson$JsonParser$NumberType = new int[org.codehaus.jackson.JsonParser.NumberType.values().length];
                try
                {
                    $SwitchMap$org$codehaus$jackson$JsonParser$NumberType[org.codehaus.jackson.JsonParser.NumberType.INT.ordinal()] = 1;
                }
                catch(NoSuchFieldError ex) { }
                try
                {
                    $SwitchMap$org$codehaus$jackson$JsonParser$NumberType[org.codehaus.jackson.JsonParser.NumberType.LONG.ordinal()] = 2;
                }
                catch(NoSuchFieldError ex) { }
                $SwitchMap$org$codehaus$jackson$JsonToken = new int[JsonToken.values().length];
                try
                {
                    $SwitchMap$org$codehaus$jackson$JsonToken[JsonToken.VALUE_STRING.ordinal()] = 1;
                }
                catch(NoSuchFieldError ex) { }
                try
                {
                    $SwitchMap$org$codehaus$jackson$JsonToken[JsonToken.VALUE_NUMBER_INT.ordinal()] = 2;
                }
                catch(NoSuchFieldError ex) { }
                try
                {
                    $SwitchMap$org$codehaus$jackson$JsonToken[JsonToken.VALUE_NUMBER_FLOAT.ordinal()] = 3;
                }
                catch(NoSuchFieldError ex) { }
                try
                {
                    $SwitchMap$org$codehaus$jackson$JsonToken[JsonToken.VALUE_EMBEDDED_OBJECT.ordinal()] = 4;
                }
                catch(NoSuchFieldError ex) { }
                try
                {
                    $SwitchMap$org$codehaus$jackson$JsonToken[JsonToken.VALUE_TRUE.ordinal()] = 5;
                }
                catch(NoSuchFieldError ex) { }
                try
                {
                    $SwitchMap$org$codehaus$jackson$JsonToken[JsonToken.VALUE_FALSE.ordinal()] = 6;
                }
                catch(NoSuchFieldError ex) { }
                try
                {
                    $SwitchMap$org$codehaus$jackson$JsonToken[JsonToken.START_ARRAY.ordinal()] = 7;
                }
                catch(NoSuchFieldError ex) { }
                try
                {
                    $SwitchMap$org$codehaus$jackson$JsonToken[JsonToken.FIELD_NAME.ordinal()] = 8;
                }
                catch(NoSuchFieldError ex) { }
                try
                {
                    $SwitchMap$org$codehaus$jackson$JsonToken[JsonToken.END_OBJECT.ordinal()] = 9;
                }
                catch(NoSuchFieldError ex) { }
            }
        }

        switch(_cls1..SwitchMap.org.codehaus.jackson.JsonToken[t.ordinal()])
        {
        case 1: // '\001'
            return deserializeFromString(jp, ctxt);

        case 2: // '\002'
        case 3: // '\003'
            return deserializeFromNumber(jp, ctxt);

        case 4: // '\004'
            return jp.getEmbeddedObject();

        case 5: // '\005'
        case 6: // '\006'
        case 7: // '\007'
            return deserializeUsingCreator(jp, ctxt);

        case 8: // '\b'
        case 9: // '\t'
            return deserializeFromObject(jp, ctxt);
        }
        throw ctxt.mappingException(getBeanClass());
    }

会先去获取当前的JSONToken值,解析一开始都是JsonToken.START_OBJECT,所以走jp.nextToken()方法,调用的是ReaderBasedParser.nextToken():

public JsonToken nextToken()
        throws IOException, JsonParseException
    {
        if(_currToken == JsonToken.FIELD_NAME)
            return _nextAfterName();
        if(_tokenIncomplete)
            _skipString();
        int i = _skipWSOrEnd();
        if(i < 0)
        {
            close();
            return _currToken = null;
        }
        _tokenInputTotal = (_currInputProcessed + (long)_inputPtr) - 1L;
        _tokenInputRow = _currInputRow;
        _tokenInputCol = _inputPtr - _currInputRowStart - 1;
        _binaryValue = null;
        if(i == 93)
        {
            if(!_parsingContext.inArray())
                _reportMismatchedEndMarker(i, '}');
            _parsingContext = _parsingContext.getParent();
            return _currToken = JsonToken.END_ARRAY;
        }
        if(i == 125)
        {
            if(!_parsingContext.inObject())
                _reportMismatchedEndMarker(i, ']');
            _parsingContext = _parsingContext.getParent();
            return _currToken = JsonToken.END_OBJECT;
        }
        if(_parsingContext.expectComma())
        {
            if(i != 44)
                _reportUnexpectedChar(i, (new StringBuilder()).append("was expecting comma to separate ").append(_parsingContext.getTypeDesc()).append(" entries").toString());
            i = _skipWS();
        }
        boolean inObject = _parsingContext.inObject();
        if(inObject)
        {
            String name = _parseFieldName(i);
            _parsingContext.setCurrentName(name);
            _currToken = JsonToken.FIELD_NAME;
            i = _skipWS();
            if(i != 58)
                _reportUnexpectedChar(i, "was expecting a colon to separate field name and value");
            i = _skipWS();
        }
        JsonToken t;
        switch(i)
        {
        case 34: // '"'
            _tokenIncomplete = true;
            t = JsonToken.VALUE_STRING;
            break;

        case 91: // '['
            if(!inObject)
                _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol);
            t = JsonToken.START_ARRAY;
            break;

        case 123: // '{'
            if(!inObject)
                _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol);
            t = JsonToken.START_OBJECT;
            break;

        case 93: // ']'
        case 125: // '}'
            _reportUnexpectedChar(i, "expected a value");
            // fall through

        case 116: // 't'
            _matchToken(JsonToken.VALUE_TRUE);
            t = JsonToken.VALUE_TRUE;
            break;

        case 102: // 'f'
            _matchToken(JsonToken.VALUE_FALSE);
            t = JsonToken.VALUE_FALSE;
            break;

        case 110: // 'n'
            _matchToken(JsonToken.VALUE_NULL);
            t = JsonToken.VALUE_NULL;
            break;

        case 45: // '-'
        case 48: // '0'
        case 49: // '1'
        case 50: // '2'
        case 51: // '3'
        case 52: // '4'
        case 53: // '5'
        case 54: // '6'
        case 55: // '7'
        case 56: // '8'
        case 57: // '9'
            t = parseNumberText(i);
            break;

        default:
            t = _handleUnexpectedValue(i);
            break;
        }
        if(inObject)
        {
            _nextToken = t;
            return _currToken;
        } else
        {
            _currToken = t;
            return t;
        }
    }

这个方法很重要,就是通过遍历json字符串,来获取分隔符,根据分隔符来获取key值,判断字符的方法是int i = _skipWSOrEnd():

关于fastjson和jackson将json字符串解析成实体的过程(二)

然后回到上个方法,看这部分:

关于fastjson和jackson将json字符串解析成实体的过程(二)

进入_parseFieldName方法:

关于fastjson和jackson将json字符串解析成实体的过程(二)

这个主要是获取key值,也就是字段名,_inputPtr是字符串当前下标,_inputEnd是字符串的总长度,_inputBuffer是该json的字符数组

         if(ch == 34){
              int start = _inputPtr;
              _inputPtr = ptr + 1;
              return _symbols.findSymbol(_inputBuffer, start, ptr - start, hash);
          }
          break;

如果字符是双引号(第二个),则返回该字段名。

关于fastjson和jackson将json字符串解析成实体的过程(二)

这个方法也是判断字符,同理。

最后部分:

JsonToken t;
        switch(i)
        {
        case 34: // '"'
            _tokenIncomplete = true;
            t = JsonToken.VALUE_STRING;
            break;

        case 91: // '['
            if(!inObject)
                _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol);
            t = JsonToken.START_ARRAY;
            break;

        case 123: // '{'
            if(!inObject)
                _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol);
            t = JsonToken.START_OBJECT;
            break;

        case 93: // ']'
        case 125: // '}'
            _reportUnexpectedChar(i, "expected a value");
            // fall through

        case 116: // 't'
            _matchToken(JsonToken.VALUE_TRUE);
            t = JsonToken.VALUE_TRUE;
            break;

        case 102: // 'f'
            _matchToken(JsonToken.VALUE_FALSE);
            t = JsonToken.VALUE_FALSE;
            break;

        case 110: // 'n'
            _matchToken(JsonToken.VALUE_NULL);
            t = JsonToken.VALUE_NULL;
            break;

        case 45: // '-'
        case 48: // '0'
        case 49: // '1'
        case 50: // '2'
        case 51: // '3'
        case 52: // '4'
        case 53: // '5'
        case 54: // '6'
        case 55: // '7'
        case 56: // '8'
        case 57: // '9'
            t = parseNumberText(i);
            break;

        default:
            t = _handleUnexpectedValue(i);
            break;
        }
        if(inObject)
        {
            _nextToken = t;
            return _currToken;
        } else
        {
            _currToken = t;
            return t;
        }

就是根据当前字符来获取JsonToken的值,并传递给_nextToken或者_currToken。

返回BeanDeserializer.deserialize方法,进入deserializeFromObject(jp, ctxt),这个就是解析最主要的方法:

public Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt)
        throws IOException, JsonProcessingException
    {
        if(_defaultConstructor == null)
        {
            if(_propertyBasedCreator != null)
                return _deserializeUsingPropertyBased(jp, ctxt);
            if(_delegatingCreator != null)
                return _delegatingCreator.deserialize(jp, ctxt);
            if(_beanType.isAbstract())
                throw JsonMappingException.from(jp, (new StringBuilder()).append("Can not instantiate abstract type ").append(_beanType).append(" (need to add/enable type information?)").toString());
            else
                throw JsonMappingException.from(jp, (new StringBuilder()).append("No suitable constructor found for type ").append(_beanType).append(": can not instantiate from JSON object (need to add/enable type information?)").toString());
        }
        Object bean = constructDefaultInstance();
        for(; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken())
        {
            String propName = jp.getCurrentName();
            jp.nextToken();
            SettableBeanProperty prop = _beanProperties.find(propName);
            if(prop != null)
            {
                try
                {
                    prop.deserializeAndSet(jp, ctxt, bean);
                }
                catch(Exception e)
                {
                    wrapAndThrow(e, bean, propName, ctxt);
                }
                continue;
            }
            if(_ignorableProps != null && _ignorableProps.contains(propName))
            {
                jp.skipChildren();
                continue;
            }
            if(_anySetter != null)
                try
                {
                    _anySetter.deserializeAndSet(jp, ctxt, bean, propName);
                }
                catch(Exception e)
                {
                    wrapAndThrow(e, bean, propName, ctxt);
                }
            else
                handleUnknownProperty(jp, ctxt, bean, propName);
        }

        return bean;
    }

生成了一个object,然后根据JsonToken值循环,当JsonToken.END_OBJECT时候结束,当JsonToken改为FIELD_NAME,获取当前的key值,然后循环调用jp.nextToken(),JsonToken改为STRING_VALUE,拿到json字符串的value值,根据反射拿到setter字段名的方法,调用prop.deserializeAndSet(jp, ctxt, bean)给属性赋值。所以这跟你json字符串末尾是什么符号并没什么关系,它是面向对象的思想。

关于fastjson和jackson将json字符串解析成实体的过程(二)

关于fastjson和jackson将json字符串解析成实体的过程(二)

这里对value为null也作了处理:

关于fastjson和jackson将json字符串解析成实体的过程(二)

后面就没什么了,返回bean,清除资源之类的收尾工作。

jackson测试版本比较老,1.7.6,我在网上查的文档是1.9.9,所以这里有部分方法最新版没有。

所以经过这次查看源码,发现jackson还是比较全面的,推荐使用。