tommwq.work/aip

AIP-146 泛化域

· [tommwq@126.com]
编号 146
原文链接 https://google.aip.dev/146
状态 批准
创建日期 2019-05-28
更新日期 2019-05-28

API中的大多数域,无论是在请求、资源还是自定义应答中,都有具体的类型或模式。这个模式是约定的一部分,开发者依此约定进行编码。

然而,偶尔会有一些泛化或多态域,可以符合多种模式,甚至是完全可以是任意形式的。

指南

虽然泛化域往往很少见,服务 可以 在必要时使用泛化域。根据域需要的泛化程度,有几种方法可以做到这一点;一般来说,服务 应当 尝试使用能够满足用例的“最低泛化”方法。

Oneof

oneof 可以 用于引入联合类型:用户或服务可以指定 oneof 中的一个域。此外 oneof 可以 可以包含同类型域(通常是字符串),表示选项之间存在语义差异。

由于 oneof 中的各个域使用不同的键,开发者可以通过编程确定使用哪个(如果有)域。

oneof 在最大程度上保留了每个选项的类型安全和语义信息,相对于其他泛化或多态选项,服务 应当 优先使用 oneof 。然而,如果存在大量(或无限)的备选项,或者对于需要一系列“级联oneof”的大型资源结构, oneof 结构是不合适的。

注意 向现有的 oneof 添加额外的备选域是非破坏性变更,但将现有域移入或移出 oneof 是破坏性变更(这会在Go protobuf stubs中产生无法向后兼容的变更)。

Maps

Maps 可以 用于存在许多 同类型 值,但键未知或键由用户决定的情况。

Maps通常不适合泛化域,因为map值共享同一类型。偶尔也是有用的。特别是map有时可以用于存在许多同类型对象,并根据键的 名字 产生不同行为的情况(如使用键作为环境 名字 )。

Struct

google.protobuf.Struct对象 可以 用于表示任意嵌套JSON。键是字符串,值可以是浮点数、字符串、布尔值、数组或者另外的嵌套结构,允许表示为JSON的任意嵌套结构(并且在使用REST/JSON时自动表示为JSON)。

如果服务预先不指导模式,或者服务需要存储和检索任意的结构化用户数据, Struct 用处最大。此时使用 Struct 对用户来说非常方便,可以轻松获得JSON对象,在客户端环境中方便的操作。

如果服务需要推理 Struct模式应当 使用JSONSchema实现这一目的。JSONSchema本身就是JSON,可以存储在 Struct 中。

Any

google.protobuf.Any对象可用于发送任意序列化的protocol buffer消息和类型定义。

但这增加了复杂性,如果消费者无法访问proto定义, Any 除了传递无效数据外,对任何实际任务都没有用处。即使消费者 确实 有proto定义,也必须确保类型已注册,并执行手动反序列化。开发者往往不熟悉这个过程。

因此,除非其他方案行不通, 不应 使用 Any