io.bitsensor.lib.jackson.protobuf.ProtobufDeserializer Maven / Gradle / Ivy
The newest version!
package io.bitsensor.lib.jackson.protobuf;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import io.bitsensor.proto.shaded.com.google.protobuf.Message;
import io.bitsensor.proto.shaded.com.google.protobuf.MessageOrBuilder;
import io.bitsensor.proto.shaded.com.google.protobuf.util.JsonFormat;
import io.bitsensor.proto.shaded.com.google.protobuf.util.JsonFormat.Parser;
import java.io.IOException;
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);
}
String source = parser.getCodec().readTree(parser).toString();
try {
// Converts reader into proto-compatible json before parsing.
String message = toProtoJson(source, UNFLATTEN_EXCLUDED_FIELDS).toString();
this.parser.merge(message, builder);
} catch (IOException e) {
throw context.mappingException(e.getMessage());
}
return finish(builder);
}
private MessageOrBuilder finish(Message.Builder builder) {
if (build) {
return builder.build();
} else {
return builder;
}
}
}