Home > Net >  How to parse protocol buffer message and create json out of it?
How to parse protocol buffer message and create json out of it?

Time:08-24

Here is my minimal .proto file:

syntax = "proto3";

message getDhtParams {}

message DhtContents {
    string dht_contents=1;
}

service MyApp {
    rpc getDhtContent(getDhtParams) returns (DhtContents) {}
}

Two things to note related to the above proto file:

  1. It is a minimal file. There is a lot more to it.
  2. The server is already generated and running. The server is implemented in Python.

I am writing client in Go. And this is the fetching code I have come up with:

func fetchDht() (*pb.DhtContents, error) {
    // Set up a connection to the server.
    address := "localhost:9998"
    conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()

    client := pb.NewMyAppClient(conn)

    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()

    r, err := client.GetDhtContent(ctx, &pb.GetDhtParams{})

    if err != nil {
        return nil, errors.New("could not get dht contents")
    }
    return r, nil
}

For sake of simplicity, I have tripped down the output, but the output looks something like this:

dht_contents:"{'node_ids': ['dgxydhlqoopevxv'], 'peer_addrs': [['192.168.1.154', '41457']], 'peer_meta': [{'peer_id': {'nodeID': 'dgxydhlqoopevxv', 'key': 'kdlvjdictuvgxspwkdizqryr', 'mid': 'isocvavbtzkxeigkkrubzkcx', 'public_key': 'uhapwxnfeqqmnojsaijghhic', '_address': 'xklqlebqngpkxb'}, 'ip_addrs': ['192.168.1.154', '41457'], 'services': [{'service_input': '', 'service_output': '', 'price': 0}], 'timestamp': 1661319968}]}"

A few things to note about this response:

  1. It starts with dht_contents: which I know is a field of DhtContents message.
  2. This could be an issue from the server side; in that case I will inform the service developer. But the json enclosed is not a valid JSON as it uses single quotes.

My questions:

  1. What is an elegant way to deal with that dht_contents? There must be the protobuf/grpc way. I aim to get the contents between double quotes.
  2. How do I convert the content to JSON? I have already created the struct to unmarshal.

It would be enough if I am also able to convert the response which is of type *pb.DhtContents to []byte, from there I can convert it to JSON.

CodePudding user response:

  1. The generated code should have a method which will get rid of dht_contents:" from the start and " from the end.

In your case, that method should be called GetDhtContents().

You can modify your fetchDht function to something like this:

func fetchDht() (string, error) {
    address := "localhost:9998"
    // ...
    if err != nil {
        return nil, errors.New("could not get dht contents")
    }
    return r.GetDhtContents(), nil
}
  1. From there on, you can work on making it a valid JSON by replacing single quotes to double quotes. Or it may be handled on the service end.

CodePudding user response:

  1. there is the methods generated by proto file to get the content from the result(the "r"), then use r.Get..., you could get the content.
  2. convert string to the type you want. suggest:
  3. change proto type to bytes
  4. then json.Unmarshal([r.Get...],[dst])
  • Related