fern-api / fern

Input OpenAPI. Output SDKs and Docs.
https://buildwithfern.com
MIT License
2.45k stars 118 forks source link

[Bug] allOf with multiple schemas ignores the ones that are union types (oneOf) #3955

Open alansartorio opened 5 days ago

alansartorio commented 5 days ago

Describe the Bug

When a schema uses allOf with multiple schemas and one of those is defined with oneOf, the "oneOf" schema gets ignored from the outer schema.

Information to Reproduce

Run the generator using the sample openapi.yaml provided below, and notice there's no field of type Inner nor any way to set it's fields in the Test class.

CLI Version

0.31.7

Generator Version

fernapi/fern-java-spring 0.9.0

API Definition

OpenAPI specification to reproduce the bug.

openapi: 3.1.0
info:
  version: 1.0.0
  title: Example
servers:
  - url: http://api.example.xyz/v1

paths:
components:
  schemas:
    Variant1:
      properties:
        field2:
          type: string
      required: [field2]

    Variant2:
      properties:
        field3:
          type: string
      required: [field3]

    Inner:
      oneOf:
        - $ref: '#/components/schemas/Variant1'
        - $ref: '#/components/schemas/Variant2'
      discriminator:
        propertyName: type
        mapping:
          FIRST: '#/components/schemas/Variant1'
          SECOND: '#/components/schemas/Variant2'

    Inner2:
      properties:
        field:
          type: string
      required: [field]

    Test:
      allOf:
        - $ref: '#/components/schemas/Inner'
        - $ref: '#/components/schemas/Inner2'

Test is the schema that uses allOf and Inner the one that uses oneOf.

These would be examples of data for the schema Test:

{
    "field": "hello",
    "type": "FIRST",
    "field2": "hello"
}
{
    "field": "hello",
    "type": "SECOND",
    "field3": "hello"
}

Actual SDK

The buggy SDK that is produced:

class types/Test.java

/**
 * This file was auto-generated by Fern from our API Definition.
 */

package types;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import core.ObjectMappers;
import java.lang.Object;
import java.lang.String;
import java.util.Objects;

@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonDeserialize(
    builder = Test.Builder.class
)
public final class Test implements IInner2 {
  private final String field;

  private Test(String field) {
    this.field = field;
  }

  @JsonProperty("field")
  @java.lang.Override
  public String getField() {
    return field;
  }

  @java.lang.Override
  public boolean equals(Object other) {
    if (this == other) return true;
    return other instanceof Test && equalTo((Test) other);
  }

  private boolean equalTo(Test other) {
    return field.equals(other.field);
  }

  @java.lang.Override
  public int hashCode() {
    return Objects.hash(this.field);
  }

  @java.lang.Override
  public String toString() {
    return ObjectMappers.stringify(this);
  }

  public static FieldStage builder() {
    return new Builder();
  }

  public interface FieldStage {
    _FinalStage field(String field);

    Builder from(Test other);
  }

  public interface _FinalStage {
    Test build();
  }

  @JsonIgnoreProperties(
      ignoreUnknown = true
  )
  public static final class Builder implements FieldStage, _FinalStage {
    private String field;

    private Builder() {
    }

    @java.lang.Override
    public Builder from(Test other) {
      field(other.getField());
      return this;
    }

    @java.lang.Override
    @JsonSetter("field")
    public _FinalStage field(String field) {
      this.field = field;
      return this;
    }

    @java.lang.Override
    public Test build() {
      return new Test(field);
    }
  }
}

It included the String field but not the Inner field.

Expected SDK

The class Test should have a field of type Inner, or another way to set the fields from that schema.

Additional Context

It might be the same issue as https://github.com/fern-api/fern/issues/2377 , but in his example I can't see any use of allOf with multiple schemas.

I'm not familiar with the IL produced, but I don't see mentions of Inner in the type_:Test section, making me think this issue is not specific to the generator I used (fernapi/fern-java-spring).