I am receiving messages in protobuf format. I need to convert it to json format fast as all my business logic is written to handle json based POJO objects.
byte[] request = ..; // msg received
// convert to intermediate POJO
AdxOpenRtb.BidRequest bidRequestProto = AdxOpenRtb.BidRequest.parseFrom(request, reg);
// convert intermediate POJO to json string.
// THIS STEP IS VERY SLOW
Printer printer = JsonFormat.printer().printingEnumsAsInts().omittingInsignificantWhitespace();
String jsonBody = printer.print(bidRequestProto);
// convert json string to final POJO format
BidRequest bidRequest = super.parse(jsonBody.getBytes());
Proto object to json conversion step is very slow. Is there any faster approach for it?
can i reuse printer
object? is it thread-safe?
Note: This POJO class (AdxOpenRtb.BidRequest
& BidRequest
) is very complex having many hierarchy and fields but contains similar data with slightly different fields name and data types.
2
Answers
I end up using
MapStruct
as suggested by some of you (@M.Deinum).new code:
Code snippet of
BidRequestMapper
:The new approach is 20-50x faster in my local test environment.
It's worth mentioning that
MapStruct
is an annotation processor which makes it much faster than other similar libraries which use reflection and it also has very good support for customization.I ran into some performance issues as well and ended up writing the QuickBuffers library. It generates dedicated JSON serialization methods (i.e. no reflection) and should give you a 10-30x speedup. It can be used side-by-side with Google’s implementation. The code should look something like this:
JsonSinkBenchmark has some sample code for replacing the built-in JSON encoder with more battle-tested Gson/Jackson backends.
Edit: if you’re doing this within a single process and are worried about performance, you’re better off writing or generating code to convert the Java objects directly. JSON is not a very efficient format to go through.