【发布时间】:2020-04-26 10:22:08
【问题描述】:
情况
我正在为现有代码库制定 OpenAPI v3 规范。该方法基于 jaxrs (jersey) 上下文中的 swagger-core。 API 需要支持由顶点(具有属性的实体)和边(连接顶点,可能具有属性)组成的图。对于 json(反)序列化,我们依赖于 jackson。
模型(与图表相关)类似于:
Vertex:
type: object
...
properties:
id:
type: string
...
Edge:
type: object
...
properties:
start:
$ref: '#/components/schemas/Vertex'
destination:
$ref: '#/components/schemas/Vertex'
问题/挑战
有两个问题:
- 开销:这种模式(以及我们如何使用它)将导致顶点在边的开始和目标字段中重复。这是不必要的有效负载,对于大顶点(可能属性/大值)和引用这些顶点的许多边来说可能是相当大的。
- 正确性:更严重的问题是可能不清楚哪个顶点是正确的顶点。 IE。 Vertex 的多个实例可能出现在具有相同 id 但具有不同值的请求/响应中。这似乎容易出错。
解决方法
在 API 端,我们可以使用@JsonIdentityInfo 和@JsonIdentityReference 来解决这些问题。但是,似乎不可能生成使用此功能的客户端。
我想这里的主要问题是 OpenAPI 规范/JSON 模式缺乏支持对象引用的支持。
在我的“谷歌努力”中,围绕 OAS / JSON 模式本身的引用的内容使水域变得混乱......看图。
我一直在研究 JSON Reference 和 Javascript Object Graph,但我没有发现将这些想法纳入 OAS 架构的挂钩。
模型引用为字符串
对我来说最可能采取的方法是将Edge 的起始和目标属性建模为strings。这至少解决了上述问题。这确实带来了一个新问题:swagger 生成的客户端使用起来不太直观:
new Edge()
.start(vertexA.getId())
.destination(vertexB.getId())
而不是
new Edge()
.start(vertexA)
.destination(vertexB)
即使阅读回复,问题也会变得更糟:
Vertex start = graph.getVertices().stream()
.filter(v -> v.getId().equals(edge.getStart()))
.findFirst();
Vertex destination = graph.getVertices().stream()
.filter(v -> v.getId().equals(edge.getDestination()))
.findFirst();
而不是
Vertex start = edge.getStart();
Vertex destination = edge.getDestination();
更糟糕的是,API 将为Vertex 和Edge 提供一个类层次结构。当使用 string 作为起始和目标属性的类型时,客户端中的类型安全性就落空了。
帮助
有人对这种模式有经验吗?关于如何在客户端生成器中建模架构和/或支持的任何建议?
【问题讨论】: