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

io.bitsensor.lib.jackson.protobuf.ProtobufDeserializer Maven / Gradle / Ivy

The newest version!
package io.bitsensor.lib.jackson.protobuf;

import io.bitsensor.plugins.shaded.com.fasterxml.jackson.core.JsonParser;
import io.bitsensor.plugins.shaded.com.fasterxml.jackson.core.JsonToken;
import io.bitsensor.plugins.shaded.com.fasterxml.jackson.databind.DeserializationContext;
import io.bitsensor.plugins.shaded.com.fasterxml.jackson.databind.JsonMappingException;
import io.bitsensor.plugins.shaded.com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import io.bitsensor.proto.shaded.io.bitsensor.proto.shaded.com.google.protobuf.Message;
import io.bitsensor.proto.shaded.io.bitsensor.proto.shaded.com.google.protobuf.MessageOrBuilder;
import io.bitsensor.proto.shaded.io.bitsensor.proto.shaded.com.google.protobuf.util.JsonFormat;
import io.bitsensor.proto.shaded.io.bitsensor.proto.shaded.com.google.protobuf.util.JsonFormat.Parser;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

import static io.bitsensor.lib.entity.util.ProtoUtils.UNFLATTEN_EXCLUDED_FIELDS;
import static io.bitsensor.lib.entity.util.ProtoUtils.toProtoJson;

public class ProtobufDeserializer extends StdDeserializer {
    private final T defaultInstance;
    private final boolean build;
    private final Parser parser;

    public ProtobufDeserializer(Class messageType, boolean build) throws JsonMappingException {
        this(messageType, build, JsonFormat.parser());
    }

    @SuppressWarnings("unchecked")
    public ProtobufDeserializer(Class messageType, boolean build, Parser parser) throws JsonMappingException {
        super(messageType);

        try {
            this.defaultInstance = (T) messageType.getMethod("getDefaultInstance").invoke(null);
        } catch (Exception e) {
            throw new JsonMappingException("Unable to get default instance for type " + messageType, e);
        }

        this.build = build;
        this.parser = parser;
    }

    @Override
    public MessageOrBuilder deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        Message.Builder builder = defaultInstance.newBuilderForType();

        JsonToken token = parser.getCurrentToken();
        if (token == JsonToken.START_ARRAY) {
            token = parser.nextToken();
        }

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

        Object inputSource = parser.getInputSource();
        final Reader reader;
        if (inputSource instanceof Reader) {
            reader = (Reader) inputSource;
        } else {
            reader = new StringReader(parser.readValueAsTree().toString());
        }

        try {
            // Converts reader into proto-compatible json before parsing.
            String message = toProtoJson(readerToString(reader), UNFLATTEN_EXCLUDED_FIELDS).toString();
            this.parser.merge(message, builder);

        } catch (IOException e) {
            throw context.mappingException(e.getMessage());
        }

        return finish(builder);
    }

    private String readerToString(Reader reader) throws IOException {
        char[] arr = new char[8 * 1024];
        StringBuilder buffer = new StringBuilder();
        int numCharsRead;
        while ((numCharsRead = reader.read(arr, 0, arr.length)) != -1) {
            buffer.append(arr, 0, numCharsRead);
        }
        reader.close();
        return buffer.toString();
    }

    private MessageOrBuilder finish(Message.Builder builder) {
        if (build) {
            return builder.build();
        } else {
            return builder;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy