Jackson Application 2 full data binding

Source: Internet
Author: User

The second application of Data Binding is full data binding. That is, it supports Conversion Between Custom Java classes and JSON objects.

The following code demonstrates a simple usage:

Class response definition:

import lombok.Getter;import lombok.Setter;/** * * @author chenshu */public class Response {        @Getter @Setter    private String status;        @Getter @Setter    private String message;}

Call code:

public class App {    public static void main( String[] args ) throws IOException {        ObjectMapper mapper = new ObjectMapper(); // create once, reuse        String jsonSource = "{\"message\":\"Login succeeded!\",\"status\":null}";        Response response = mapper.readValue(jsonSource, Response.class);                String result = mapper.writeValueAsString(response);    }}

Obtain the source code by running the MVN dependency: Sources command. Then you can debug and enter the code for observation.

The internal code of the readvalue method is as follows:

    @SuppressWarnings("unchecked")    public <T> T readValue(String content, Class<T> valueType)        throws IOException, JsonParseException, JsonMappingException    {     // !!! TODO//    _setupClassLoaderForDeserialization(valueType);        return (T) _readMapAndClose(_jsonFactory.createJsonParser(content), _typeFactory.constructType(valueType));    } 

_ Typefactory. constructtype (valuetype) uses the response parameter. class creates a simpletype object (a subclass of javatype). When it is created, a linkedhashmap object is used as a cache. If it has already been created, it will not be created again, therefore, multithreading locks are also used. Refer to the Code in typefactory. Java:

    /**     * @param context Mapping of formal parameter declarations (for generic     *   types) into actual types     */    protected JavaType _fromClass(Class<?> clz, TypeBindings context)    {        // Very first thing: small set of core types we know well:        if (clz == String.class) return CORE_TYPE_STRING;        if (clz == Boolean.TYPE) return CORE_TYPE_BOOL;        if (clz == Integer.TYPE) return CORE_TYPE_INT;        if (clz == Long.TYPE) return CORE_TYPE_LONG;                // Barring that, we may have recently constructed an instance:        ClassKey key = new ClassKey(clz);        JavaType result;                synchronized (_typeCache) {            result = _typeCache.get(key);        }        if (result != null) {            return result;        }        // If context was needed, weed do:        /*        if (context == null) {            context = new TypeBindings(this, cls);        }        */                // First: do we have an array type?        if (clz.isArray()) {            result = ArrayType.construct(_constructType(clz.getComponentType(), null), null, null);        /* Also: although enums can also be fully resolved, there's little         * point in doing so (T extends Enum<T>) etc.         */        } else if (clz.isEnum()) {            result = new SimpleType(clz);        /* Maps and Collections aren't quite as hot; problem is, due         * to type erasure we often do not know typing and can only assume         * base Object.         */        } else if (Map.class.isAssignableFrom(clz)) {            result = _mapType(clz);        } else if (Collection.class.isAssignableFrom(clz)) {            result =  _collectionType(clz);        } else {            result = new SimpleType(clz);        }                synchronized (_typeCache) {            _typeCache.put(key, result);        }                return result;    }

I did not perform any further tracing, but I guess I will use response. Class. getmethods () to obtain and call the setstatus and setmessage methods of response.

Let's look at the call code:

return (T) _readMapAndClose(_jsonFactory.createJsonParser(content), _typeFactory.constructType(valueType));

_ Jsonfactory. createjsonparser (content) creates the jsonparser object in the Jackson streaming library.

_jsonFactory.createJsonParser(content)

The following code comes from the jsonfactory. Java of the streaming library.

    /**     * Method for constructing parser for parsing     * contents of given String.     */    public JsonParser createJsonParser(String content)        throws IOException, JsonParseException    {Reader r = new StringReader(content);        // true -> we own the Reader (and must close); not a big deal        IOContext ctxt = _createContext(r, true);        // [JACKSON-512]: allow wrapping with InputDecorator        if (_inputDecorator != null) {            r = _inputDecorator.decorate(ctxt, r);        }return _createJsonParser(r, ctxt);    }

Here, I just want to know how to use stringreader to read JSON strings. Because it belongs to the content of the streaming library, put it first.

To read an object from a JSON string, you need to use the object called deserialization. This object is created only once and then cached.

The code in the objectmapper. Java class is as follows:

    /**     * Method called to locate deserializer for the passed root-level value.     */    protected JsonDeserializer<Object> _findRootDeserializer(DeserializationContext ctxt,            JavaType valueType)        throws JsonMappingException    {        // First: have we already seen it?        JsonDeserializer<Object> deser = _rootDeserializers.get(valueType);        if (deser != null) {            return deser;        }        // Nope: need to ask provider to resolve it        deser = ctxt.findRootValueDeserializer(valueType);        if (deser == null) { // can this happen?            throw new JsonMappingException("Can not find a deserializer for type "+valueType);        }        _rootDeserializers.put(valueType, deser);        return deser;    }

The _ rootdeserializers variable type is concurrenthashmap <javatype, jsondeserializer <Object>, so it is thread-safe.

Conclusion:

1. For each custom type, only one javatype (actually a subclass simpletype) is created and cached in the linkedhashmap variable. The cache variable is located in the typefactory variable of the objectmapper object.

2. Each custom type has only one deserialization parser, Which is cached in the concurrenthashmap <javatype, jsondeserializer <Object> variable and is the objectmapper variable.

3. To ensure efficiency, try to use only one objectmapper object. Since the cache reading and updating of 1 and 2 are both thread-safe and other code is thread-safe, it is also safe to use an objectmapper object in a multi-threaded environment.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.