【问题标题】:Object graphs in swagger clientsswagger 客户端中的对象图
【发布时间】: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 ReferenceJavascript 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 将为VertexEdge 提供一个类层次结构。当使用 string 作为起始和目标属性的类型时,客户端中的类型安全性就落空了。

帮助

有人对这种模式有经验吗?关于如何在客户端生成器中建模架构和/或支持的任何建议?

【问题讨论】:

    标签: openapi swagger-codegen


    【解决方案1】:

    我的经历完全一样,尤其是在 google 搜索方面:有很多 JSON 模式引用命中,它们都与复杂的对象图序列化无关。

    我在服务器端 (java) 做了什么:我有自己的对象序列化程序,它足够聪明,可以处理对象引用。每个对象都有一个 id。当对象第一次序列化时,序列化器的输出是对象 JSON 表示。当一个对象在图中再次出现时,序列化器只输出带有#objectid的对象引用。

    例如:

        {
        "created": "05/03/2020 17:49:08",
        "name": "Object Group [5109]",
        "objectID": 5109,
        "elements": [
            {
                "created": "05/03/2020 17:49:08",
                "name": "Element [5110]",
                "description": "Object example [5109]",
                "objectID": 5110
                "parent": #5109
            },
           ...
        ]
    }
    

    当然,如果你想在客户端正确地表示对象图,这必须在 JavaScript 代码中反序列化,并在反序列化期间设置客户端对象引用。我不知道在 openapi 生成的客户端中有什么机制。

    【讨论】:

    • 这不是放弃了使用 OpenAPI Schema 的意义吗?或任何架构?在我们的设置中,我们使用杰克逊,它对您所描述的内容有很好的支持;见fasterxml.github.io/jackson-annotations/javadoc/2.8/com/… 和朋友。我的问题更接近于:我们如何在 OAS API 中表达这一点,以便从它生成的客户端“正常工作”;即在请求/响应中进行对象重复数据删除,同时在生成的模型代码中仍然具有完整的对象图。
    猜你喜欢
    • 2018-04-13
    • 2017-05-31
    • 1970-01-01
    • 2016-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多