microsoft / microsoft/typespec
protobuf emitter maps unknown to Any (should have an option for Struct)
- Dominant language
- Java
- Stars
- 5.9k
- Forks
- 394
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 104
Description
Our TypeSpec has several free form "arbitrary JSON object" fields authored as plain YAML maps. they're typed `unknown` in TypeSpec, but the emitter renders them as `google.protobuf.Any`. `Any` requires a `@type` URL to be set in the JSON representation so a plain YAML object like `{foo: 1}` cannot be parsed into the field. Arbitrary JSON should map to `google.protobuf.Struct` or `google.protobuf.Value`.
it would be nice if there were decorators to determine what protobuf type is generated here.
[Playground Link](https://typespec.io/playground/?tspconfig=ZW1pdDoKICAtICJAdHlwZXNwZWMvcHJvdG9idWYiCg%3D%3D&c=aW1wb3J0ICJAdHlwZXNwZWMvcHJvdG9idWYiOwoKdXNpbmcgVHlwZVNwZWMuUMcbOwoKQHBhY2thZ2UoewogIG5hbWU6ICJyZXBybyIsCn0pCsQSc3BhY2UgUsQVOwoKbW9kZWwgVGjEUcQ0QGZpZWxkKDEpyUBzdHJpbmc7CgogIC8vIEZyZWUtZm9ybSwgYXJiaXRyYXJ5IEpTT04gb2JqZWN0IGF1dGhvcmVkIGFzIGEgcGxhaW4gWUFNTC%2FFJW1hcCwgZS5nLiB7IGZvbzogMSB9LsZaV2Ugd2FudCB0aGlzIHRvIGJlIGdvb2dsZS7oAPsuU3RydWN0IGluIHRoZSBlbWl0dGVkIMUfxEXnALwy5AC8YXJndW1lbnRzPzogdW5rbm93bjsKfQ%3D%3D&vs=%7B%7D)
## Minimal playground spec
```tsp
import "@typespec/protobuf";
using TypeSpec.Protobuf;
@package({
name: "repro",
})
namespace Repro;
model Thing {
@field(1)
name: string;
// Free-form, arbitrary JSON object authored as a plain YAML/JSON map, e.g. { foo: 1 }.
// We want this to be google.protobuf.Struct in the emitted proto.
@field(2)
arguments?: unknown;
}
```
## Actual emitter output
```proto
syntax = "proto3";
package repro;
import "google/protobuf/any.proto";
message Thing {
string name = 1;
google.protobuf.Any arguments = 2;
}
```
## Expected / desired output
```proto
syntax = "proto3";
package repro;
import "google/protobuf/struct.proto";
message Thing {
string name = 1;
google.protobuf.Struct arguments = 2;
}
```
## Ask
`unknown` represents "any JSON value", which round-trips through `google.protobuf.Struct`
(object) / `google.protobuf.Value` (any value) - not `google.protobuf.Any`, whose JSON form
requires a `@type` URL. Options for the emitter:
1. Map `unknown` to `google.protobuf.Value` (or `Struct` for object-shaped data) by default; or
2. Provide an opt-in decorator / config to choose the well-known mapping (e.g.
`@TypeSpec.Protobuf.wellKnownType(Struct)`).
Either removes the need for downstream post-processing of the generated `.proto`.
Contributor guide
Research direction
Start with the linked Playground and minimal TypeSpec spec, then trace the protobuf emitter behavior for unknown. Compare the generated Any output with the requested Struct or Value mapping and determine how an option or decorator should select it; done means the example emits the selected well-known protobuf type without post-processing.
Written by the indexing model from the issue text.
Assessment
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100