net.nullschool.grains.jackson.datatype.AbstractBasicConstMapDeserializer.java Source code

Java tutorial

Introduction

Here is the source code for net.nullschool.grains.jackson.datatype.AbstractBasicConstMapDeserializer.java

Source

/*
 * Copyright 2013 Cameron Beccario
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.nullschool.grains.jackson.datatype;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.type.MapType;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 2013-06-11<p/>
 *
 * @author Cameron Beccario
 */
abstract class AbstractBasicConstMapDeserializer<T> extends StdDeserializer<T> implements ContextualDeserializer {

    private static final long serialVersionUID = 1;

    final MapType mapType;
    final KeyDeserializer keyDeserializer;
    final JsonDeserializer<?> valueDeserializer;
    final TypeDeserializer valueTypeDeserializer;

    AbstractBasicConstMapDeserializer(MapType mapType, KeyDeserializer keyDeserializer,
            JsonDeserializer<?> valueDeserializer, TypeDeserializer valueTypeDeserializer) {

        super(mapType.getRawClass());
        this.mapType = mapType;
        this.keyDeserializer = keyDeserializer;
        this.valueDeserializer = valueDeserializer;
        this.valueTypeDeserializer = valueTypeDeserializer;
    }

    abstract JsonDeserializer<?> withDeserializers(KeyDeserializer keyDeserializer,
            JsonDeserializer<?> valueDeserializer, TypeDeserializer valueTypeDeserializer);

    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property)
            throws JsonMappingException {

        KeyDeserializer kd = keyDeserializer != null ? keyDeserializer
                : ctxt.findKeyDeserializer(mapType.getKeyType(), property);
        JsonDeserializer<?> vd = valueDeserializer != null ? valueDeserializer
                : ctxt.findContextualValueDeserializer(mapType.getContentType(), property);
        TypeDeserializer vtd = valueTypeDeserializer != null ? valueTypeDeserializer.forProperty(property) : null;

        return withDeserializers(kd, vd, vtd);
    }

    @Override
    public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer)
            throws IOException {

        return typeDeserializer.deserializeTypedFromObject(jp, ctxt);
    }

    abstract T emptyResult();

    abstract T resultOf(Object key, Object value);

    abstract T asResult(List<Object> keys, List<Object> values);

    @Override
    public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        JsonToken token = jp.getCurrentToken();
        if (token == JsonToken.START_OBJECT) {
            token = jp.nextToken();
        } else if (token != JsonToken.FIELD_NAME) {
            throw ctxt.mappingException(mapType.getRawClass());
        }

        if (token == JsonToken.END_OBJECT) {
            return emptyResult();
        }

        KeyDeserializer kd = keyDeserializer;
        JsonDeserializer<?> vd = valueDeserializer;
        TypeDeserializer vtd = valueTypeDeserializer;

        List<Object> keys = null;
        List<Object> values = null;
        Object key;
        Object value;
        do {
            String name = jp.getCurrentName();
            key = kd == null ? name : kd.deserializeKey(name, ctxt);
            value = jp.nextToken() != JsonToken.VALUE_NULL
                    ? vtd == null ? vd.deserialize(jp, ctxt) : vd.deserializeWithType(jp, ctxt, vtd)
                    : null;

            token = jp.nextToken();
            if (keys == null) {
                if (token == JsonToken.END_OBJECT) {
                    return resultOf(key, value);
                }
                keys = new ArrayList<>();
                values = new ArrayList<>();
            }
            keys.add(key);
            values.add(value);
        } while (token != JsonToken.END_OBJECT);

        return asResult(keys, values);
    }
}