27

Hey I know there is a solution for this in Java, I'm curious to know if anyone knows of a Python 3 solution for converting a JSON object or file into protobuf format. I would accept either or as converting to an object is trivial. Searching the stackoverflow site, I only found examples of protobuf->json, but not the other way around. There is one extremely old repo that may do this but it is in Python 2 and our pipeline is Python 3. Any help is as always, appreciated.

2
  • protobufs have a schema, so you would de-serialize your JSON and then serialize to protobuf using a schema. what have you tried so far? Commented Feb 21, 2020 at 20:12
  • That sounds about right. Basically there is this file format that previously used JSON, and we simply want to serialize it to valid protobuf, so that we can test the deserialization of the protobuf back to a JSON which can be passed into the API. So far I have not really even understood what is correct to try. google.protobuf.json_format.ParseDict seems like it may be a viable solution, but am having trouble interpreting if this message format is the format we are most likely to receive for protobuf input if it is via a RESTful API. Commented Feb 21, 2020 at 20:17

2 Answers 2

56

The library you're looking for is google.protobuf.json_format. You can install it with the directions in the README here. The library is compatible with Python >= 2.7.

Example usage:

Given a protobuf message like this:

message Thing {
    string first = 1;
    bool second = 2;
    int32 third = 3;
}

You can go from Python dict or JSON string to protobuf like:

import json

from google.protobuf.json_format import Parse, ParseDict

d = {
    "first": "a string",
    "second": True,
    "third": 123456789
}

message = ParseDict(d, Thing())
# or
message = Parse(json.dumps(d), Thing())    

print(message.first)  # "a string"
print(message.second) # True
print(message.third)  # 123456789

or from protobuf to Python dict or JSON string:

from google.protobuf.json_format import MessageToDict, MessageToJson

message_as_dict = MessageToDict(message)
message_as_dict['first']  # == 'a string'
message_as_dict['second'] # == True
message_as_dict['third']  # == 123456789
# or
message_as_json_str = MessageToJson(message)

The documentation for the json_format module is here.

Sign up to request clarification or add additional context in comments.

3 Comments

if you see my comment above I do suggest google.protobuf.json_format. why would you use Parse instead of ParseDict and which is more practical for a protobuf being piped to an API? basically trying to get a protobuf from an external source like FHIR, then pipe to a RESTful API in python
I just used Parse since I consume raw JSON strings more than dicts. Are you trying to go the other way? I.e. from message to JSON? In that case you can use MessageToJson or MessageToDict. Not sure if I'm understanding your question.
I am trying to parse a message to JSON but I need a test protobuf stream with relevant data for us to parse so basically, JSON to message piped out of python, then piped through the API, then parsed back into JSON because we will be receiving either JSONs or Protobufs
3

Here is a much simpler way by using xia-easy-proto module. No need to pre-define anything.

pip install xia-easy-proto

And then

from xia_easy_proto import EasyProto


if __name__ == '__main__':
    songs = {"composer": {'given_name': 'Johann', 'family_name': 'Pachelbel'},
             "title": 'Canon in D',
             "year": [1680, 1681]}
    song_class, song_payload = EasyProto.serialize(songs)
    print(song_class)  # It is the message class
    print(song_payload)  # It is the serialized message

4 Comments

This is really helpful. Looking for a long time. Could you just open source it so anyone can help improve it. It is really useful. thanks
and how is the performance? will the serialize cost too much for each record than protobuf with already generated class?
How do you think of MakeSimpleProtoClass() in google/protobuf/proto_builder.py; see google/protobuf/internal/proto_builder_test.py?
All documentation could be found in the related pip help pages. There is no performance issue if you could reuse the message class. I will think about open sourcing it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.