OpenAPITools / OpenAPITools/openapi-generator

[BUG] [Help!!!]Using oneOf and discriminator, should the generated class, subclass and parent class have an inheritance relationship?

Open
#12,612 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist

Using the code generated by oneof and discriminator, for example, in the Java language, if there is no inheritance relationship between subclasses and parent classes, how to use it?

for example:
yaml is:

TIMMsgElement:
      oneOf:
        - $ref: '#/components/schemas/TIMTextElem'
        - $ref: '#/components/schemas/TIMLocationElem'
        - $ref: '#/components/schemas/TIMFaceElem'
      discriminator:
        propertyName: MsgType
    TIMTextElem:
      type: object
      required: [ MsgType, MsgContent ]
      properties:
        MsgType:
          type: string
          default: TIMTextElem
          description: TIM 消息对象类型
        MsgContent:
          type: object
          description: 对于每种 MsgType 用不同的 MsgContent 格式
          required: [ Text ]
          properties:
            Text:
              type: string
    TIMLocationElem:
      type: object
      required: [ MsgType, MsgContent ]
      properties:
        MsgType:
          type: string
          default: TIMLocationElem
        MsgContent:
          type: object
          required: [ Longitude, Latitude, Desc ]
          properties:
            Longitude:
              type: number
            Latitude:
              type: number
            Desc:
              type: string
    TIMFaceElem:
      type: object
      required: [ MsgType, MsgContent ]
      properties:
        MsgType:
          type: string
          default: TIMFaceElem
        MsgContent:
          type: object
          required: [ Index, Data ]
          properties:
            Index:
              type: integer
            Data:
              type: string

Generated code:

import java.util.Objects;
import java.util.Arrays;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.annotation.JsonValue;
import com.tencentcloudapi.im.model.TIMCustomElem;
import com.tencentcloudapi.im.model.TIMFaceElem;
import com.tencentcloudapi.im.model.TIMFileElem;
import com.tencentcloudapi.im.model.TIMImageElem;
import com.tencentcloudapi.im.model.TIMLocationElem;
import com.tencentcloudapi.im.model.TIMSoundElem;
import com.tencentcloudapi.im.model.TIMTextElem;
import com.tencentcloudapi.im.model.TIMVideoFileElem;
import com.tencentcloudapi.im.model.TIMVideoFileElemMsgContent;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.annotation.JsonTypeName;
import javax.validation.constraints.*;
import javax.validation.Valid;
import org.hibernate.validator.constraints.*;

/**
 * TIMMsgElement
 */
@JsonPropertyOrder({
  TIMMsgElement.JSON_PROPERTY_MSG_TYPE,
  TIMMsgElement.JSON_PROPERTY_MSG_CONTENT
})

@JsonIgnoreProperties(
  value = "MsgType", // ignore manually set MsgType, it will be automatically generated by Jackson during serialization
  allowSetters = true // allows the MsgType to be set during deserialization
)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "MsgType", visible = true)
@JsonSubTypes({
  @JsonSubTypes.Type(value = TIMCustomElem.class, name = "TIMCustomElem"),
  @JsonSubTypes.Type(value = TIMFaceElem.class, name = "TIMFaceElem"),
  @JsonSubTypes.Type(value = TIMFileElem.class, name = "TIMFileElem"),
  @JsonSubTypes.Type(value = TIMImageElem.class, name = "TIMImageElem"),
  @JsonSubTypes.Type(value = TIMLocationElem.class, name = "TIMLocationElem"),
  @JsonSubTypes.Type(value = TIMSoundElem.class, name = "TIMSoundElem"),
  @JsonSubTypes.Type(value = TIMTextElem.class, name = "TIMTextElem"),
  @JsonSubTypes.Type(value = TIMVideoFileElem.class, name = "TIMVideoFileElem"),
})

public class TIMMsgElement {
  public static final String JSON_PROPERTY_MSG_TYPE = "MsgType";
  protected String msgType = "TIMVideoFileElem";

  public static final String JSON_PROPERTY_MSG_CONTENT = "MsgContent";
  private TIMVideoFileElemMsgContent msgContent;

  public TIMMsgElement() { 
  }

  public TIMMsgElement msgType(String msgType) {
    
    this.msgType = msgType;
    return this;
  }

   /**
   * Get msgType
   * @return msgType
  **/
  @javax.annotation.Nonnull
  @NotNull
  @ApiModelProperty(required = true, value = "")
  @JsonProperty(JSON_PROPERTY_MSG_TYPE)
  @JsonInclude(value = JsonInclude.Include.ALWAYS)

  public String getMsgType() {
    return msgType;
  }


  @JsonProperty(JSON_PROPERTY_MSG_TYPE)
  @JsonInclude(value = JsonInclude.Include.ALWAYS)
  public void setMsgType(String msgType) {
    this.msgType = msgType;
  }


  public TIMMsgElement msgContent(TIMVideoFileElemMsgContent msgContent) {
    
    this.msgContent = msgContent;
    return this;
  }

   /**
   * Get msgContent
   * @return msgContent
  **/
  @javax.annotation.Nonnull
  @NotNull
  @Valid
  @ApiModelProperty(required = true, value = "")
  @JsonProperty(JSON_PROPERTY_MSG_CONTENT)
  @JsonInclude(value = JsonInclude.Include.ALWAYS)

  public TIMVideoFileElemMsgContent getMsgContent() {
    return msgContent;
  }


  @JsonProperty(JSON_PROPERTY_MSG_CONTENT)
  @JsonInclude(value = JsonInclude.Include.ALWAYS)
  public void setMsgContent(TIMVideoFileElemMsgContent msgContent) {
    this.msgContent = msgContent;
  }


  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    TIMMsgElement tiMMsgElement = (TIMMsgElement) o;
    return Objects.equals(this.msgType, tiMMsgElement.msgType) &&
        Objects.equals(this.msgContent, tiMMsgElement.msgContent);
  }

  @Override
  public int hashCode() {
    return Objects.hash(msgType, msgContent);
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("class TIMMsgElement {\n");
    sb.append("    msgType: ").append(toIndentedString(msgType)).append("\n");
    sb.append("    msgContent: ").append(toIndentedString(msgContent)).append("\n");
    sb.append("}");
    return sb.toString();
  }

  /**
   * Convert the given object to string with each line indented by 4 spaces
   * (except the first line).
   */
  private String toIndentedString(Object o) {
    if (o == null) {
      return "null";
    }
    return o.toString().replace("\n", "\n    ");
  }

}


Among them, msgBody is given the type TIMVideoFileElemMsgContent by default. Can't other types be used?

If I want to set a TimMsgElemMent of type TIMFaceElem, how do I use it?

        SendGroupMsgRequest sendGroupMsgRequest = new SendGroupMsgRequest(); // SendGroupMsgRequest |
        sendGroupMsgRequest.setMsgBody(new ArrayList<TIMMsgElement>());

The project address is: https://github.com/TencentCloud/tencentcloud-im-sdk-java
very urgent! ! !

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the YAML schema with the Java generator and inspect the generated TIMMsgElement and TIMFaceElem classes, focusing on oneOf and discriminator handling. Check existing Java generator tests for inheritance and discriminator cases. Done means the expected relationship and construction or serialization behavior are covered by a regression test, or the issue is narrowed to a confirmed generator limitation.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, openapi
Domain
backend-api-design, devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.