io.bitsensor.lib.jackson.protobuf.ProtobufDeserializer Maven / Gradle / Ivy
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 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 - 2025 Weber Informatics LLC | Privacy Policy