googleapis / googleapis/google-cloud-go

firestore: opt-in support for json struct tags when firestore struct tag is not available

Open
#10,545 3 comments 0 reactions 1 assignee Claimed by @bhshkh View on GitHub
api: firestore type: feature request
Dominant language
Go
Stars
4.5k
Forks
1.6k
Avg merge
1d 13h
Merged PRs (30d)
109

Description

**Is your feature request related to a problem? Please describe.**

We would prefer that Firebase serializes our objects in a way that is consistent with the JSON or YAML representation and with the [JSON style guide](https://google.github.io/styleguide/jsoncstyleguide.xml#Property_Name_Format).

We use proto to define and generate some of our request structs. We store the request as a field on one of our objects which is then stored in Firebase. These fields use property keys which don't align with the other object fields because the proto generated structs have `json` tags but no `firebase` tags. The default golang representation does not match the JSON style guide.

There is no built-in mechanism for proto to generate arbitrary struct tags, and the feature is rejected by the go proto team. [This comment from 2016](https://github.com/golang/protobuf/issues/52#issuecomment-243606932) shows another engineer having the same exact problem as us.

Besides this issue, it is very, very common for structs to have `json` or `yaml` tags defined. When Firebase ignores those tags, it uses an object representation which doesn't align with the other way those structs are being serialized. We would like it to be consistent.

This issue is particularly problematic for services which involve multiple languages, since the default representation may differ.

**Describe the solution you'd like**

Allow users to configure the client library in a way that it uses the `json` or `yaml` tags when a `firebase` tag is not present. This is a breaking change so it must be opt-in.

Example:

```
type Foo struct {
Bar string `json:"baz"`
}

func main() {
// Note: this is just one way it could be done. I'm open to any API which allows us to enable the feature.
cl, err := firestore.NewClientWithJSONTags(context.Context(), "my-project")
if err != nil {
log.Fatalf("Failed to create client: %s", err)
}
v := Foo{
Bar: "my-value",
}
_, err := c.Collection("my-collection").Doc("my-doc").Create(ctx, v)
if err != nil {
log.Fatalf("Failed to create Foo in Firestore: %s", err)
}
}
```

Results in a document which has `baz` as a key, instead of the go language default `Bar`.

```
{
"baz": "my-value"
}
```

**Describe alternatives you've considered**

Setting the `firebase` tag on our protos.

Caveats:

- This isn't supported directly and requires third-party plugins contributed by individual developers. There's no obvious, standout plugin that is well-maintained and battle-tested.
- We have no control over the upstream protos that our protos import, so we still can't achieve consistency across our entire object.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.