Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a protobuf to JSON using Jackson?

I get the following error while converting a protobuf to JSON using Jackson's ObjectMapper:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 
Direct self-reference leading to cycle (through reference chain:
MyObjectPb$MyObject["unknownFields"]->
com.google.protobuf.UnknownFieldSet["defaultInstanceForType"])

MyObjectPb has the following field:

protected com.google.protobuf.UnknownFieldSet unknownFields

As I am working on an existing codebase, I have the following constraints:

  1. I can't modify the source code for MyObjectPb, so I can't use Jackson's ignore annotations in MyObjectPb.
  2. Neither can I use Gson's libraries to convert the object, as the codebase already uses Jackson for serialization. Adding a new dependency is not recommended.

How do I tell Jackson to ignore (de)serializing the UnknownFieldSet object inside MyObjectPb?


I have tried the following, but these approaches do not seem to solve the problem:

a) Configuring the ObjectMapper:

myObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
myObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

b) Using a Jackson Mixin:

@JsonIgnoreType
private abstract class UnknownFieldSetIgnoreMixIn {}

myObjectMapper.addMixIn(UnknownFieldSet.class, UnknownFieldSetIgnoreMixIn.class)
like image 394
amad-person Avatar asked Jul 30 '18 07:07

amad-person


People also ask

Can protobuf be converted to JSON?

Nested Class SummaryA Printer converts protobuf message to JSON format. A TypeRegistry is used to resolve Any messages in the JSON conversion.

Does protobuf use JSON?

JSON is limited to certain python objects, and it cannot serialize every python object. Protobuf supports a wider range of data types when compared to JSON. For example, enumerations and methods are supported by Protobuf and not supported by JSON. JSON supports only a subset of python data types.

Is protobuf like JSON?

Protocol buffers provide a language-neutral, platform-neutral, extensible mechanism for serializing structured data in a forward-compatible and backward-compatible way. It's like JSON, except it's smaller and faster, and it generates native language bindings.


2 Answers

The current way (Oct-2018) to serialize a protobuf is to use com.google.protobuf.util.JsonFormat in the following manner:

JsonFormat.printer().print(myMessageOrBuilder)

I used the @JsonSerialize(using = MyMessageSerializer.class) annotation right before my protobuf object and added this class:

public static class MyMessageSerializer extends JsonSerializer<Message> {
    @Override
    public void serialize(Message message, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeRawValue(JsonFormat.printer().print(message));
    }
}

This allowed new ObjectMapper().writeValueAsString(wrapperObject) to properly convert my protobuf to JSON.

like image 73
M H Chu Avatar answered Sep 18 '22 16:09

M H Chu


I used the JsonFormat class (com.googlecode.protobuf.format.JsonFormat) to convert the protobuf:

new JsonFormat().printToString(myObject)

This did the job perfectly for me.

like image 24
amad-person Avatar answered Sep 19 '22 16:09

amad-person