Skip to content

encoding: provide canonical output format #1121

Open
@bufdev

Description

@bufdev

https://go-review.googlesource.com/c/protobuf/+/151340 added internal/detrand to denote to users that they should not rely on the stability of output. This is used for example in encoding/protojson to add a space between json key/value pairs depending on hash of the binary.

Users often want to rely on some outputs having the same format, for example:

  • Some users store JSON versions of Protobuf messages on disk. Adding a space to random serializations will result in the resulting files being different, causing differences on commits for example.
  • Testing on output becomes impossible. Although this is an explicit goal in the release notes, this is recognized in protobuf-go directly as internally, detrand.Disable is frequently called in testing:
internal/filedesc/desc_test.go:28:	detrand.Disable()
internal/encoding/json/encode_test.go:20:func init() { detrand.Disable() }
internal/encoding/text/encode_test.go:20:func init() { detrand.Disable() }
internal/msgfmt/format_test.go:30:	detrand.Disable()
encoding/prototext/encode_test.go:27:	detrand.Disable()
encoding/protojson/encode_test.go:33:func init() { detrand.Disable() }
testing/protocmp/xform_test.go:21:	detrand.Disable()

In our own tests, we had output switch between:

{"path":"a.proto","start_line":11,"start_column":10,"end_line":11,"end_column":13,"type":"FIELD_LOWER_SNAKE_CASE","message":"Field name \"Baz\" should be lower_snake_case, such as \"baz\"."}

And:

{"path":"a.proto", "start_line":11, "start_column":10, "end_line":11, "end_column":13, "type":"FIELD_LOWER_SNAKE_CASE", "message":"Field name \"Baz\" should be lower_snake_case, such as \"baz\"."}

This took us about 45 minutes to figure out, we thought our code was broken, and we found this package eventually.

I am not aware of other JSON packages (stdlib, otherwise) that do this in general. It's reasonable to allow users to disable this if they want - can detrand be made into a public package, or at least detrand.Disable be exposed in a public package?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions