Skip to content

Add readyOnly/writeOnly support #807

Open

Description

@hactar

Motivation

Currently the generator does not support readOnly and writeOnly, which is present in both 3.0 and 3.1. These attributes can be useful when generating RESTful APIs, for example if you have an ID that is generated on the server, so when you POST, there should not be a required ID field. but when you GET, the ID field is required in the response. The result would be that the same component would sometimes have a field that is optional, and sometimes not, depending on usage context.

Proposed solution

I guess adding this is not trivial, the generator would have to generate two different versions of components, one for the request, and one for the response? Or would there be a smarter way of doing this?

Alternatives considered

No response

Additional information

Is there a way you people currently work around this? Do you manually maintain two versions of the same component in the yaml file for example?

Activity

  1. czechboy0 commented on Aug 12, 2025

    @czechboy0
    Contributor

    Hi @hactar,

    thanks for filing this. I agree this is an interesting question and I'm not sure I have a solution right now. Generating all schemas twice seems like a step too far, but I also want us to stay faithful to the spec.

    Do you know what other typesafe language generators do?

  2. added
    area/generatorAffects: plugin, CLI, config file.
    and removed
    status/triageCollecting information required to triage the issue.
    on Aug 12, 2025
  3. hactar commented on Aug 12, 2025

    @hactar
    Author

    Do you know what other typesafe language generators do?

    While I was googling for information on readOnly and writeOnly, I stumbled across this discussion - a different framework with the same issue. Maybe that discussion is useful input. OpenAPITools/openapi-generator#4190

    Personally I have not worked with a framework that has this available yet, our back team and our client team are trying to clean up an API we use where as a workaround we currently send "0" - and other meaningless values such as creation dates that are ignored by the server during POST as the server is supposed to generate those - to the server during the POSTs, but we need those values to be required during GET. It's messy and while researching of how to solve this via openapi, readOnly and writeOnly were mentioned as the solution to that problem, which makes sense I'd say.

  4. czechboy0 commented on Aug 12, 2025

    @czechboy0
    Contributor

    A manual way, which I've generally used, is to define separate types for POSTs (creation) and GETs (fetching). For example, unique IDs are often assigned by the server, so it shouldn't need to be in the POST at all.

    For example, check out this example of "*Request" types: https://github.com/swiftlang/swift-server-todos-tutorial/blob/0f7b57bd180ff3b3ca620fdda65141712d941040/Completed/Sources/SwiftServerTodos/openapi.yaml#L100

    In a way, readOnly/writeOnly are just a first class way to represent this coupling of two related schemas.

  5. ManuW commented on Nov 9, 2025

    @ManuW

    Do you know what other typesafe language generators do?

    We use readOnly and writeOnly in our OpenAPI files and a lot of generators / tools do not support this. But some do support this. I have here two examples:

    Modified Pet Store

    My modified pet store example :

    ...
    components:
      schemas:
        Pet:
          type: object
          required:
            - id
            - name
          properties:
            id:
              type: integer
              format: int64
              readOnly: true
            name:
              type: string
            secret:
              type: string
              writeOnly: true
    ...
    

    Generator Hey API

    Hey API generates two types: Pet and PetWritable.

    Generated TypeScript code:

    ...
    export type Pet = {
        readonly id: number;
        name: string;
    };
    
    ...
    
    export type PetWritable = {
        name: string;
        secret?: string;
    };
    ...
    

    Generator typescript-fetch (OpenAPI Generator)

    The generator typescript-fetch from the OpenAPI Generator uses a different approach. In short, there is a PetToWeb and PetFromWeb functions that handles the writeOnly and readOnly fields.

    Generated code example:

    export interface Pet {
        readonly id: number;
        name: string;
        secret?: string;
    }
    
    /**
     * Check if a given object implements the Pet interface.
     */
    export function instanceOfPet(value: object): value is Pet {
        if (!('id' in value) || value['id'] === undefined) return false;
        if (!('name' in value) || value['name'] === undefined) return false;
        return true;
    }
    
    export function PetFromJSON(json: any): Pet {
        return PetFromJSONTyped(json, false);
    }
    
    export function PetFromJSONTyped(json: any, ignoreDiscriminator: boolean): Pet {
        if (json == null) {
            return json;
        }
        return {
            
            'id': json['id'],
            'name': json['name'],
            'secret': json['secret'] == null ? undefined : json['secret'],
        };
    }
    
    export function PetToJSON(json: any): Pet {
        return PetToJSONTyped(json, false);
    }
    
    export function PetToJSONTyped(value?: Omit<Pet, 'id'> | null, ignoreDiscriminator: boolean = false): any {
        if (value == null) {
            return value;
        }
    
        return {
            'name': value['name'],
            'secret': value['secret'],
        };
    }
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions