Convert Java POJO With Protobuf field to JSON Using Jackson

In this blog post, I will explain how to convert a regular Java class that contains a Protobuf message field to JSON using the Jackson library, for example, in a Spring Boot application as a return value of an @Controller method.

You might wonder, how this is such a big deal? After all, you can create complex POJO hierarchies, and Jackson will pick them up just fine. Well, maybe this error message will convince you.

o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [
    Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: 
    Type definition error: [simple type, class com.google.protobuf.UnknownFieldSet]; 
    nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle 
    (through reference chain: com.thecodeslinger.ppjs.web.dto.AwesomeDto["awesomePowerUp"]
        ->com.thecodeslinger.ppjs.proto.AwesomePowerUpOuterClass$AwesomePowerUp["unknownFields"]
        ->com.google.protobuf.UnknownFieldSet["defaultInstanceForType"])] with root cause

Java classes that you create with the Protobuf compiler require their JSON converter JsonFormat.Printer. So, how can we get Jackson and JsonFormat.Printer love each other and have a wedding together?

Simple: we create a custom JsonSerializer.

public class ProtobufSerializer extends JsonSerializer<Message> {

    private final JsonFormat.Printer protobufJsonPrinter = JsonFormat.printer();

    @Override
    public void serialize(Message anyProtobufMessage, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
            throws IOException {
        // The magic sauce: use the Protobuf JSON converter to write a raw JSON
        // string of the Protobuf message instance.
        jsonGenerator.writeRawValue(protobufJsonPrinter.print(anyProtobufMessage));
    }
}

This class is very simple and can work with any Protobuf Message class instance. This way, it is universal and only needs to be written once. The main ingredient is the jsonGenerator.writeRawValue method that takes the input without modification. Since we already ensure a proper JSON format using Protobuf’s converter, this is no problem in this case. Otherwise, be careful with this method.

The last step is to annotate the Message field in the POJO, so Jackson knows what to do.

@JsonSerialize(using = ProtobufSerializer.class)
private final AwesomePowerUpOuterClass.AwesomePowerUp awesomePowerUp;

You can find a complete working example that uses Spring Boot and a REST endpoint on my Github account.

Install Minikube in VirtualBox on Remote Machine for Kubectl

At work, we are using Kubernetes as a way to run our application services. To test and debug deployments before they go into code review and to the development environment, a local Kubernetes is beneficial. That is where Minikube comes into play. Unfortunately for me, our application services require more resources than my work laptop can provide, especially RAM. Either I close all applications and run Minikube, or I have a helpful browser and IDE window open 😉.

Since I need the local K8s cluster from time to time, I wondered if I could run it on my personal computer and access it from my laptop. This way, I can dedicate at least six physical cores and 24 GB of RAM to the VM (even more, but that was a nice number and more than enough).

Read More »