简体   繁体   English

如何将 protoc-gen-go gzipped FileDescriptorProto 显示为纯文本?

[英]How to display protoc-gen-go gzipped FileDescriptorProto as plaintext?

protoc-gen-go generates something like this, at the end of the generated go files: protoc-gen-go在生成的 go 文件的末尾生成类似这样的内容:


var fileDescriptor_13c75530f718feb4 = []byte{
    // 2516 bytes of a gzipped FileDescriptorProto
    0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x59, 0xdf, 0x6f, 0x1c, 0x47,
...
}

I want to read it in plaintext for debugging purposes.我想以纯文本形式阅读它以进行调试。 How to do that?怎么做?

Why I want it - a small change that should not produce change in this generated file does , and I am figuring out why (and it is hard to debug, as it's just a binary blob).为什么我想要它 - 一个应该在这个生成的文件产生变化的小变化,我正在弄清楚原因(并且很难调试,因为它只是一个二进制 blob)。

I wrote a code like this, to parse and print the blob.我写了一个这样的代码来解析和打印 blob。

The key logic is actually from https://github.com/grpc/grpc-go/blob/759de4dd00c25745b6f3d7a9fdfb32beaf1d838e/reflection/serverreflection.go#L202-L226关键逻辑其实来自https://github.com/grpc/grpc-go/blob/759de4dd00c25745b6f3d7a9fdfb32beaf1d838e/reflection/serverreflection.go#L202-L226

package main

import (
    "bytes"
    "compress/gzip"
    "encoding/json"
    "fmt"

    "io/ioutil"

    proto "github.com/golang/protobuf/proto"
    dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
    _ [here write path to your generated go source]
    // include the line above if you want to use proto.FileDescriptor,
    // leave if you just copy-paste the bytes below
)

func main() {
    // here write the path that is used in the generated file
    // in init(), as an argument to proto.RegisterFile 
    // (or just copypaste the bytes instead of using proto.FileDescriptor)
    bytes := proto.FileDescriptor(XXX)

    fd, err := decodeFileDesc(bytes)
    if err != nil {
        panic(err)
    }
    b, err := json.MarshalIndent(fd,"","  ")
    if err != nil {
        panic(err)
    }
    fmt.Println(string(b))
}

// decompress does gzip decompression.
func decompress(b []byte) ([]byte, error) {
    r, err := gzip.NewReader(bytes.NewReader(b))
    if err != nil {
        return nil, fmt.Errorf("bad gzipped descriptor: %v", err)
    }
    out, err := ioutil.ReadAll(r)
    if err != nil {
        return nil, fmt.Errorf("bad gzipped descriptor: %v", err)
    }
    return out, nil
}

func decodeFileDesc(enc []byte) (*dpb.FileDescriptorProto, error) {
    raw, err := decompress(enc)
    if err != nil {
        return nil, fmt.Errorf("failed to decompress enc: %v", err)
    }

    fd := new(dpb.FileDescriptorProto)
    if err := proto.Unmarshal(raw, fd); err != nil {
        return nil, fmt.Errorf("bad descriptor: %v", err)
    }
    return fd, nil
}

This prints the data from the proto file, as a JSON.这会将 proto 文件中的数据打印为 JSON。

As Marc Gravell mentions in the comment to the other answer, the gzip compression is non-deterministic, so the same proto file can create different gzipped FileDescriptorProto on two different computers.正如 Marc Gravell 在对另一个答案的评论中提到的,gzip 压缩是不确定的,因此同一个 proto 文件可以在两台不同的计算机上创建不同的 gzip 压缩 FileDescriptorProto。

a FileDescriptorProto is not plain text ; FileDescriptorProto不是纯文本 it doesn't contain the original schema as text , but rather: it is a protobuf binary encoded instance of FileDescriptorProto as defined by descriptor.proto , containing the processed meaning of the original schema.它不包含作为 text的原始模式,而是:它是由descriptor.proto定义的FileDescriptorProto的 protobuf 二进制编码实例,包含原始模式的处理含义

So;所以; you could deserialize that payload (once de-gzipped) as a FileDescriptorProto , and use whatever reflection/metadata API is available in "go" to get that in some text form.您可以将该有效负载(一旦解压缩)反序列化为FileDescriptorProto ,并使用“go”中可用的任何反射/元数据 API 以某种文本形式获取它。 If the go implementation of protobuf includes the protobuf json (rather than binary) API, you could just call the write-json API on the FileDescriptorProto instance.如果 protobuf 的 go 实现包括 protobuf json(而不是二进制)API,则您只需在FileDescriptorProto实例上调用 write-json API。 Note: not all protobuf implementations implement the json API.注意:并非所有 protobuf 实现都实现了 json API。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM