org.hyperledger.dropwizard.hocon.HoconDeserializer.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperledger.dropwizard.hocon.HoconDeserializer.java

Source

/**
 * 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 org.hyperledger.dropwizard.hocon;

import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.typesafe.config.*;

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

public abstract class HoconDeserializer<T> extends StdDeserializer<T> {

    public HoconDeserializer(Class<T> vc) {
        super(vc);
    }

    @SuppressWarnings("unchecked")
    public static JsonDeserializer<ConfigValue> CONFIG_VALUE = new HoconDeserializer(ConfigValue.class) {
        public ConfigValue deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
            switch (jsonParser.getCurrentToken()) {
            case START_OBJECT:
                return deserializeObject(jsonParser, context);
            case START_ARRAY:
                return deserializeArray(jsonParser, context);
            default:
                return deserializeScalar(jsonParser, context);
            }
        }
    };

    @SuppressWarnings("unchecked")
    public static JsonDeserializer<ConfigList> CONFIG_LIST = new HoconDeserializer(ConfigList.class) {
        public ConfigList deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
            switch (jsonParser.getCurrentToken()) {
            case START_ARRAY:
                return deserializeArray(jsonParser, context);
            default:
                throw context.mappingException(ConfigList.class);
            }
        }
    };

    @SuppressWarnings("unchecked")
    public static JsonDeserializer<ConfigObject> CONFIG_OBJECT = new HoconDeserializer(ConfigObject.class) {
        public ConfigObject deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
            switch (jsonParser.getCurrentToken()) {
            case START_OBJECT:
                return deserializeObject(jsonParser, context);
            default:
                throw context.mappingException(ConfigObject.class);
            }
        }
    };

    @SuppressWarnings("unchecked")
    public static JsonDeserializer<Config> CONFIG = new HoconDeserializer(Config.class) {
        public Config deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
            switch (jsonParser.getCurrentToken()) {
            case START_OBJECT:
                return deserializeObject(jsonParser, context).toConfig();
            default:
                throw context.mappingException(Config.class);
            }
        }
    };

    protected ConfigObject deserializeObject(JsonParser jp, DeserializationContext ctxt) throws IOException {
        HashMap<String, Object> mapping = new HashMap<>();

        while (jp.nextToken() != JsonToken.END_OBJECT) {
            String name = jp.getCurrentName();
            JsonToken t = jp.nextToken();
            switch (t) {
            case START_ARRAY:
                mapping.put(name, deserializeArray(jp, ctxt).unwrapped());
                break;
            case START_OBJECT:
                mapping.put(name, deserializeObject(jp, ctxt).unwrapped());
                break;
            case VALUE_FALSE:
                mapping.put(name, false);
                break;
            case VALUE_TRUE:
                mapping.put(name, true);
                break;
            case VALUE_NULL:
                mapping.put(name, null);
                break;
            case VALUE_NUMBER_FLOAT:
                if (jp.getNumberType() == JsonParser.NumberType.BIG_DECIMAL) {
                    mapping.put(name, jp.getDecimalValue());
                } else {
                    mapping.put(name, jp.getDoubleValue());
                }
                break;
            case VALUE_NUMBER_INT:
                // very cumbersome... but has to be done
                switch (jp.getNumberType()) {
                case LONG:
                    mapping.put(name, jp.getLongValue());
                    break;
                case INT:
                    mapping.put(name, jp.getIntValue());
                    break;
                default:
                    mapping.put(name, jp.getBigIntegerValue());
                }
                break;
            case VALUE_STRING:
                mapping.put(name, jp.getText());
                break;
            case VALUE_EMBEDDED_OBJECT: {
                Object ob = jp.getEmbeddedObject();
                if (ob instanceof byte[]) {
                    String b64 = ctxt.getBase64Variant().encode((byte[]) ob, false);
                    mapping.put(name, b64);
                    break;
                }
            }
            default:
                throw ctxt.mappingException(_valueClass);
            }
        }
        return ConfigValueFactory.fromMap(mapping);
    }

    protected ConfigList deserializeArray(JsonParser jp, DeserializationContext ctxt) throws IOException {

        List<Object> values = new ArrayList<>();

        JsonToken t;
        while ((t = jp.nextToken()) != JsonToken.END_ARRAY) {
            switch (t) {
            case START_ARRAY:
                values.add(deserializeArray(jp, ctxt).unwrapped());
                break;
            case START_OBJECT:
                values.add(deserializeObject(jp, ctxt).unwrapped());
                break;
            case VALUE_FALSE:
                values.add(false);
                break;
            case VALUE_TRUE:
                values.add(true);
                break;
            case VALUE_NULL:
                values.add(null);
                break;
            case VALUE_NUMBER_FLOAT:
                if (jp.getNumberType() == JsonParser.NumberType.BIG_DECIMAL) {
                    values.add(jp.getDecimalValue());
                } else {
                    values.add(jp.getDoubleValue());
                }
                break;
            case VALUE_NUMBER_INT:
                // very cumbersome... but has to be done
                switch (jp.getNumberType()) {
                case LONG:
                    values.add(jp.getLongValue());
                    break;
                case INT:
                    values.add(jp.getIntValue());
                    break;
                default:
                    values.add(jp.getBigIntegerValue());
                }
                break;
            case VALUE_STRING:
                values.add(jp.getText());
                break;
            default:
                throw ctxt.mappingException(_valueClass);
            }
        }
        return ConfigValueFactory.fromIterable(values);
    }

    protected ConfigValue deserializeScalar(JsonParser jp, DeserializationContext ctxt) throws IOException {
        switch (jp.getCurrentToken()) {
        case VALUE_EMBEDDED_OBJECT:
            throw ctxt.mappingException(JsonValue.class);
        case VALUE_FALSE:
            return ConfigValueFactory.fromAnyRef(false);
        case VALUE_TRUE:
            return ConfigValueFactory.fromAnyRef(true);
        case VALUE_NULL:
            return ConfigValueFactory.fromAnyRef(null);
        case VALUE_NUMBER_FLOAT:
        // very cumbersome... but has to be done
        {
            if (jp.getNumberType() == JsonParser.NumberType.BIG_DECIMAL) {
                return ConfigValueFactory.fromAnyRef(jp.getDecimalValue());
            }
            return ConfigValueFactory.fromAnyRef(jp.getDoubleValue());
        }
        case VALUE_NUMBER_INT: {
            switch (jp.getNumberType()) {
            case LONG:
                return ConfigValueFactory.fromAnyRef(jp.getLongValue());
            case INT:
                return ConfigValueFactory.fromAnyRef(jp.getIntValue());
            default:
                return ConfigValueFactory.fromAnyRef(jp.getBigIntegerValue());
            }
        }
        case VALUE_STRING:
            return ConfigValueFactory.fromAnyRef(jp.getText());
        default: // errors, should never get here
            //        case END_ARRAY:
            //        case END_OBJECT:
            //        case FIELD_NAME:
            //        case NOT_AVAILABLE:
            //        case START_ARRAY:
            //        case START_OBJECT:
            throw ctxt.mappingException(_valueClass);
        }
    }

}