All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.jackson.map.deser.JsonNodeDeserializer Maven / Gradle / Ivy

Go to download

Data Mapper package is a high-performance data binding package built on Jackson JSON processor

There is a newer version: 1.9.13
Show newest version
package org.codehaus.jackson.map.deser;

import java.io.IOException;

import org.codehaus.jackson.*;
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.node.*;

/**
 * Deserializer that can build instances of {@link JsonNode} from any
 * Json content, using appropriate {@link JsonNode} type.
 */
public class JsonNodeDeserializer
    extends BaseNodeDeserializer
{
    /**
     * Singleton instance of generic deserializer for {@link JsonNode}
     *
     * @deprecated Use {@link #getDeserializer} accessor instead
     */
    @Deprecated
    public final static JsonNodeDeserializer instance = new JsonNodeDeserializer();

    protected JsonNodeDeserializer() { super(JsonNode.class); }

    public static JsonDeserializer getDeserializer(Class nodeClass)
    {
        if (ObjectNode.class.isAssignableFrom(nodeClass)) {
            return ObjectDeserializer.instance;
        }
        if (ArrayNode.class.isAssignableFrom(nodeClass)) {
            return ArrayDeserializer.instance;
        }
        // For others, generic one works fine
        return JsonNodeDeserializer.instance;
    }
    
    /*
    /////////////////////////////////////////////////////
    // Actual deserializer implementations
    /////////////////////////////////////////////////////
    */

    /**
     * Implementation that will produce types of any JSON nodes; not just one
     * deserializer is registered to handle (in case of more specialized handler).
     * Overridden by typed sub-classes for more thorough checking
     */
    public JsonNode deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException, JsonProcessingException
    {
        return deserializeAny(jp, ctxt);
    }

    /*
    /////////////////////////////////////////////////////
    // Specific instances for more accurate types
    /////////////////////////////////////////////////////
     */

    final static class ObjectDeserializer
        extends BaseNodeDeserializer
    {
        final static ObjectDeserializer instance = new ObjectDeserializer();

        protected ObjectDeserializer() {
            super(ObjectNode.class);
        }

        @Override
        public ObjectNode deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException
        {
            if (jp.getCurrentToken() == JsonToken.START_OBJECT) {
                jp.nextToken();
                return deserializeObject(jp, ctxt);
            }
            if (jp.getCurrentToken() == JsonToken.FIELD_NAME) {
                return deserializeObject(jp, ctxt);
            }
            throw ctxt.mappingException(ObjectNode.class);
         }
    }
        
    final static class ArrayDeserializer
        extends BaseNodeDeserializer
    {
        final static ArrayDeserializer instance = new ArrayDeserializer();

        protected ArrayDeserializer() {
            super(ArrayNode.class);
        }
        
        @Override
        public ArrayNode deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException
        {
            if (jp.getCurrentToken() == JsonToken.START_ARRAY) {
                return deserializeArray(jp, ctxt);
            }
            throw ctxt.mappingException(ArrayNode.class);
        }
    }
}

/**
 * Base class for all actual {@link JsonNode} deserializer
 * implementations
 */
abstract class BaseNodeDeserializer
    extends StdDeserializer
{
    protected JsonNodeFactory _nodeFactory;
    
    public BaseNodeDeserializer(Class nodeClass)
    {
        super(nodeClass);
        _nodeFactory = JsonNodeFactory.instance;
    }
    
    public JsonNodeFactory getNodeFactory() { return _nodeFactory; }
    public void setNodeFactory(JsonNodeFactory nf) { _nodeFactory = nf; }
    
    @Override
    public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
            TypeDeserializer typeDeserializer)
        throws IOException, JsonProcessingException
    {
        /* Output can be as JSON Object, Array or scalar: no way to know
         * a priori. So:
         */
        return typeDeserializer.deserializeTypedFromAny(jp, ctxt);
    }

    /*
    /////////////////////////////////////////////////////
    // Overridable methods
    /////////////////////////////////////////////////////
    */
    
    protected void _reportProblem(JsonParser jp, String msg)
        throws JsonMappingException
    {
        throw new JsonMappingException(msg, jp.getTokenLocation());
    }
    
    /**
     * Method called when there is a duplicate value for a field.
     * By default we don't care, and the last value is used.
     * Can be overridden to provide alternate handling, such as throwing
     * an exception, or choosing different strategy for combining values
     * or choosing which one to keep.
     *
     * @param fieldName Name of the field for which duplicate value was found
     * @param objectNode Object node that contains values
     * @param oldValue Value that existed for the object node before newValue
     *   was added
     * @param newValue Newly added value just added to the object node
     */
    protected void _handleDuplicateField(String fieldName, ObjectNode objectNode,
                                         JsonNode oldValue, JsonNode newValue)
        throws JsonProcessingException
    {
        // By default, we don't do anything
        ;
    }
    
    /*
    /////////////////////////////////////////////////////
    // Helper methods
    /////////////////////////////////////////////////////
    */
    
    protected final ObjectNode deserializeObject(JsonParser jp, DeserializationContext ctxt)
        throws IOException, JsonProcessingException
    {
        ObjectNode node = _nodeFactory.objectNode();
        JsonToken t = jp.getCurrentToken();
        if (t == JsonToken.START_OBJECT) {
            t = jp.nextToken();
        }
        for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
            String fieldName = jp.getCurrentName();
            jp.nextToken();
            JsonNode value = deserializeAny(jp, ctxt);
            JsonNode old = node.put(fieldName, value);
            if (old != null) {
                _handleDuplicateField(fieldName, node, old, value);
            }
        }
        return node;
    }
    
    protected final ArrayNode deserializeArray(JsonParser jp, DeserializationContext ctxt)
        throws IOException, JsonProcessingException
    {
        ArrayNode node = _nodeFactory.arrayNode();
        while (jp.nextToken() != JsonToken.END_ARRAY) {
            node.add(deserializeAny(jp, ctxt));
        }
        return node;
    }

    protected final JsonNode deserializeAny(JsonParser jp, DeserializationContext ctxt)
        throws IOException, JsonProcessingException
    {
        switch (jp.getCurrentToken()) {
        case START_OBJECT:
        case FIELD_NAME:
            return deserializeObject(jp, ctxt);

        case START_ARRAY:
            return deserializeArray(jp, ctxt);

        case VALUE_STRING:
            return _nodeFactory.textNode(jp.getText());

        case VALUE_NUMBER_INT:
            {
                JsonParser.NumberType nt = jp.getNumberType();
                if (nt == JsonParser.NumberType.BIG_INTEGER
                    || ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_INTEGER_FOR_INTS)) {
                    return _nodeFactory.numberNode(jp.getIntValue());
                }
                if (nt == JsonParser.NumberType.INT) {
                    return _nodeFactory.numberNode(jp.getIntValue());
                }
                return _nodeFactory.numberNode(jp.getLongValue());
            }

        case VALUE_NUMBER_FLOAT:
            {
                JsonParser.NumberType nt = jp.getNumberType();
                if (nt == JsonParser.NumberType.BIG_DECIMAL
                    || ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS)) {
                    return _nodeFactory.numberNode(jp.getDecimalValue());
                }
                return _nodeFactory.numberNode(jp.getDoubleValue());
            }

        case VALUE_TRUE:
            return _nodeFactory.booleanNode(true);

        case VALUE_FALSE:
            return _nodeFactory.booleanNode(false);

        case VALUE_NULL:
            return _nodeFactory.nullNode();

            // These states can not be mapped; input stream is
            // off by an event or two

        case END_OBJECT:
        case END_ARRAY:
        default:
            throw ctxt.mappingException(getValueClass());
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy