使用OpenAPI的“其中之一”:生成可以解析JavaSpring API TypeScript代码?

ax6ht2ek  于 2022-11-26  发布在  TypeScript
关注(0)|答案(1)|浏览(211)

我使用openapi-generator6.2.1openapi3.0.2 YAML文件生成服务器端Java Spring接口和TypeScript客户机类。
我尝试使用oneOf功能来指定特定属性可以具有以下两种确切类型之一:PublicMetadataSchemaV1ClosedMetadataSchemaV1中的一个或多个。
定义如下:

ReadRaidMetadataResponseV1:
      # Using oneOf/discriminator is probably pushing too close to the edge of 
      # what openapi-gen can do yet, for example that's why metadataSchema is a
      # string instead of an enum:
      # https://github.com/OpenAPITools/openapi-generator/pull/13846
      type: object
      description: Any type of metadata
      oneOf:
#        - $ref: 'metadata-schema-v1.yaml#/components/schemas/MetadataSchemaV1'
        - $ref: '#/components/schemas/PublicMetadataSchemaV1'
        - $ref: '#/components/schemas/ClosedMetadataSchemaV1'
      discriminator:
        propertyName: metadataSchema
        mapping:
          raido-metadata-schema-v1: '#/components/schemas/PublicMetadataSchemaV1'
          closed-metadata-schema-v1: '#/components/schemas/ClosedMetadataSchemaV1'
    PublicMetadataSchemaV1:
      description: >
        This object only exists because openapi-gen discriminator needs to be 
        a string, currently.
        See https://github.com/OpenAPITools/openapi-generator/pull/13846.
        Eventually, want the mapping to just use MetadataSchemaV1.
      type: object
      required: [ metadataSchema, id, titles, dates, access]
      # this is how we make PublicMetadataSchemaV1 inherit all the fields oneOf: 
      # MetadataSchemaV1.
      allOf: 
        - $ref: 'metadata-schema-v1.yaml#/components/schemas/MetadataSchemaV1'
      properties:
        # This is where we "override" the type of metadataSchema to be a string
        # instead of the enum that we would prefer it to be.
        # Rather than "string" this should be a "constant" with value `raido-metadata-schema-v1`
        # metadataSchema: {$ref: 'shared.yaml#/components/schemas/RaidoMetaschema' }
        metadataSchema: { type: string }
    ClosedMetadataSchemaV1:
      type: object
      required: [ metadataSchema, id, titles, dates, access]
      properties:
        # Rather than "string" this should be a "constant" with value `closed-metadata-schema-v1`
        # metadataSchema: {$ref: 'shared.yaml#/components/schemas/RaidoMetaschema' }
        metadataSchema: { type: string }
        id: {$ref: 'shared.yaml#/components/schemas/IdBlock'}
        access: {$ref: 'shared.yaml#/components/schemas/AccessBlock'}

这里的问题是JavaSpring生成器创建的代码如下所示:

@JsonIgnoreProperties(
  value = "metadataSchema", // ignore manually set metadataSchema, it will be automatically generated by Jackson during serialization
  allowSetters = true // allows the metadataSchema to be set during deserialization
)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "metadataSchema", visible = true)
@JsonSubTypes({
  @JsonSubTypes.Type(value = ClosedMetadataSchemaV1.class, name = "ClosedMetadataSchemaV1"),
  @JsonSubTypes.Type(value = PublicMetadataSchemaV1.class, name = "PublicMetadataSchemaV1"),
  @JsonSubTypes.Type(value = ClosedMetadataSchemaV1.class, name = "closed-metadata-schema-v1"),
  @JsonSubTypes.Type(value = PublicMetadataSchemaV1.class, name = "raido-metadata-schema-v1")
})

@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2022-11-21T15:03:48.931461200+10:00[Australia/Brisbane]")
public interface ReadRaidMetadataResponseV1 {
    public String getMetadataSchema();
}

并且API服务始终将“类名”Map(即PublicMetadataSchemaV1)作为值,而不是将已定义的raido-metadata-schema-v1“Map”值作为值。
但生成的TypeScript代码如下所示:

export function ReadRaidMetadataResponseV1FromJSONTyped(json: any, ignoreDiscriminator: boolean): ReadRaidMetadataResponseV1 {
    if ((json === undefined) || (json === null)) {
        return json;
    }
    switch (json['metadataSchema']) {
        case 'closed-metadata-schema-v1':
            return {...ClosedMetadataSchemaV1FromJSONTyped(json, true), metadataSchema: 'closed-metadata-schema-v1'};
        case 'raido-metadata-schema-v1':
            return {...PublicMetadataSchemaV1FromJSONTyped(json, true), metadataSchema: 'raido-metadata-schema-v1'};
        default:
            throw new Error(`No variant of ReadRaidMetadataResponseV1 exists with 'metadataSchema=${json['metadataSchema']}'`);
    }
}

因此它总是失败,因为TypeScript代码只知道(正确的)raido-metadata-schema-v1Map值。
带有完整代码的存储库是公开的,您可以在以下位置找到完整的openapi YAML文件:https://github.com/au-research/raido-v2/blob/b06c08349a58b4559768963c5e3fbb81cc2c2f28/api-svc/idl-raid-v2/src/shared.yaml#L36
的问题:如何构建我的openapi定义,或者需要使用哪些标志,以便生成的typescript-fetch代码能够实际使用JavaSpring生成器提供的API?

r8uurelv

r8uurelv1#

这个问题的简单“解决方法”答案**(*)**是,您必须将Map值设定为与Map到的类型名称相同。也就是说:

discriminator:
        propertyName: metadataSchema
        mapping:
          raido-metadata-schema-v1: '#/components/schemas/PublicMetadataSchemaV1'
          closed-metadata-schema-v1: '#/components/schemas/ClosedMetadataSchemaV1'

必须重写为:

discriminator:
        propertyName: metadataSchema
        mapping:
          PublicMetadataSchemaV1: '#/components/schemas/PublicMetadataSchemaV1'
          ClosedMetadataSchemaV1: '#/components/schemas/ClosedMetadataSchemaV1'

(*)-“简单”,但令人讨厌,而且可能很尴尬。如果有人发布的答案允许Map值是任意的,而不是被迫匹配类型名称-我会很高兴地将其标记为正确答案。

相关问题