{"id":22074246,"url":"https://github.com/rexagon/opg","last_synced_at":"2025-07-24T11:32:12.344Z","repository":{"id":40241702,"uuid":"273586856","full_name":"Rexagon/opg","owner":"Rexagon","description":"Rust OpenAPI 3.0 docs generator","archived":false,"fork":false,"pushed_at":"2023-04-05T13:48:24.000Z","size":185,"stargazers_count":36,"open_issues_count":10,"forks_count":8,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-14T13:45:51.986Z","etag":null,"topics":["openapi3","rust","swagger"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Rexagon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-06-19T21:08:55.000Z","updated_at":"2024-08-14T07:06:47.000Z","dependencies_parsed_at":"2022-09-05T13:41:12.832Z","dependency_job_id":null,"html_url":"https://github.com/Rexagon/opg","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rexagon%2Fopg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rexagon%2Fopg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rexagon%2Fopg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rexagon%2Fopg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Rexagon","download_url":"https://codeload.github.com/Rexagon/opg/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227435670,"owners_count":17776444,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["openapi3","rust","swagger"],"created_at":"2024-11-30T21:27:12.588Z","updated_at":"2024-11-30T21:27:13.148Z","avatar_url":"https://github.com/Rexagon.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003ch3 align=\"center\"\u003eopg\u003c/h3\u003e\n    \u003cp align=\"center\"\u003eRust OpenAPI 3.0 docs generator\u003c/p\u003e\n    \u003cp align=\"center\"\u003e\n        \u003ca href=\"/LICENSE\"\u003e\n            \u003cimg alt=\"GitHub\" src=\"https://img.shields.io/github/license/Rexagon/opg\" /\u003e\n        \u003c/a\u003e\n        \u003ca href=\"https://github.com/Rexagon/opg/actions?query=workflow%3Amaster\"\u003e\n            \u003cimg alt=\"GitHub Workflow Status\" src=\"https://img.shields.io/github/workflow/status/Rexagon/opg/master\" /\u003e\n        \u003c/a\u003e\n        \u003ca href=\"https://crates.io/crates/opg\"\u003e\n            \u003cimg alt=\"Crates.io Version\" src=\"https://img.shields.io/crates/v/opg\" /\u003e\n        \u003c/a\u003e\n        \u003ca href=\"https://docs.rs/opg\"\u003e\n            \u003cimg alt=\"Docs.rs\" src=\"https://docs.rs/opg/badge.svg\" /\u003e\n        \u003c/a\u003e\n    \u003c/p\u003e\n\u003c/p\u003e\n\n#### Example:\n\u003e Or see more [here](https://github.com/Rexagon/opg/tree/master/test_suite/tests)\n\n```rust\nuse opg::*;\nuse serde::{Serialize, Deserialize};\n\n#[derive(Serialize, Deserialize, OpgModel)]\n#[serde(rename_all = \"camelCase\")]\n#[opg(\"Simple enum\")]\nenum SimpleEnum {\n    Test,\n    Another,\n    Yay,\n}\n\n#[derive(Serialize, Deserialize, OpgModel)]\n#[opg(\"newtype string\", format = \"id\", example = \"abcd0001\")]\nstruct NewType(String);\n\n#[derive(Serialize, Deserialize, OpgModel)]\nstruct SimpleStruct {\n    first_field: i32,\n    #[opg(\"Field description\")]\n    second: String,\n}\n\n#[derive(Serialize, Deserialize, OpgModel)]\n#[serde(rename_all = \"kebab-case\")]\nenum ExternallyTaggedEnum {\n    Test(String),\n    AnotherTest(String, #[opg(\"Second\")] String),\n}\n\n#[derive(Serialize, Deserialize, OpgModel)]\n#[serde(untagged)]\nenum UntaggedEnum {\n    First {\n        value: NewType,\n    },\n    #[opg(\"Variant description\")]\n    Second {\n        #[opg(\"Inlined struct\", inline)]\n        another: SimpleStruct,\n    },\n}\n\n#[derive(Serialize, Deserialize, OpgModel)]\n#[serde(tag = \"tag\", rename_all = \"lowercase\")]\nenum InternallyTaggedEnum {\n    First(SimpleStruct),\n    Second { field: String },\n}\n\n#[derive(Serialize, Deserialize, OpgModel)]\n#[serde(tag = \"tag\", content = \"content\", rename_all = \"lowercase\")]\nenum AdjacentlyTaggedEnum {\n    First(String),\n    Second(NewType, NewType),\n}\n\n#[derive(Serialize, Deserialize, OpgModel)]\n#[serde(rename_all = \"camelCase\")]\nstruct TypeChangedStruct {\n    #[serde(with = \"chrono::naive::serde::ts_milliseconds\")]\n    #[opg(\"UTC timestamp in milliseconds\", integer, format = \"int64\")]\n    pub timestamp: chrono::NaiveDateTime,\n}\n\n#[derive(Serialize, Deserialize, OpgModel)]\nstruct StructWithComplexObjects {\n    #[serde(skip_serializing_if = \"Option::is_none\")]\n    #[opg(optional)]\n    super_optional: Option\u003cOption\u003cString\u003e\u003e,\n    field: Option\u003cString\u003e,\n    boxed: Box\u003cOption\u003ci32\u003e\u003e,\n}\n\n#[derive(Serialize, OpgModel)]\nstruct GenericStructWithRef\u003c'a, T\u003e {\n    message: \u0026'a str,\n    test: T,\n}\n\n#[derive(Serialize, OpgModel)]\nstruct SuperResponse {\n    simple_enum: SimpleEnum,\n    #[serde(rename = \"new_type\")]\n    newtype: NewType,\n    externally_tagged_enum: ExternallyTaggedEnum,\n    untagged_enum: UntaggedEnum,\n    internally_tagged_enum: InternallyTaggedEnum,\n    adjacently_tagged_enum: AdjacentlyTaggedEnum,\n    type_changed_struct: TypeChangedStruct,\n    struct_with_complex_objects: StructWithComplexObjects,\n}\n\n#[test]\nfn print_api() {\n    let test = describe_api! {\n        info: {\n            title: \"My super API\",\n            version: \"0.0.0\",\n        },\n        tags: {internal, admin(\"Super admin methods\")},\n        servers: {\n            \"https://my.super.server.com/v1\",\n        },\n        security_schemes: {\n            (http \"bearerAuth\"): {\n                scheme: Bearer,\n                bearer_format: \"JWT\",\n            },\n        },\n        paths: {\n            (\"hello\" / \"world\" / { paramTest: String }): {\n                summary: \"Some test group of requests\",\n                description: \"Another test description\",\n                parameters: {\n                    (header \"x-request-id\"): {\n                        description: \"Test\",\n                        required: true,\n                    },\n                },\n                GET: {\n                    tags: {internal},\n                    summary: \"Small summary\",\n                    description: \"Small description\",\n                    deprecated: true,\n                    parameters: {\n                        (query someParam: u32): {\n                            description: \"Test\",\n                        }\n                    },\n                    200: String,\n                    418 (\"Optional response description\"): String\n                },\n                POST: {\n                    tags: {admin},\n                    security: {\"bearerAuth\"},\n                    body: {\n                        description: \"Some interesting description\",\n                        schema: GenericStructWithRef\u003c'static, i64\u003e,\n                        required: true,\n                    },\n                    200: SuperResponse,\n                    callbacks: {\n                        callbackUrl: {\n                            (\"callbackUrl\"): {\n                                POST: {\n                                    200: std::vec::Vec\u003cString\u003e,\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    };\n\n    println!(\"{}\", serde_yaml::to_string(\u0026test).unwrap());\n}\n```\n\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003eResult:\u003c/b\u003e\u003c/summary\u003e\n\u003cp\u003e\n\n```yaml\n---\nopenapi: 3.0.3\ninfo:\n  title: My super API\n  version: 0.0.0\ntags:\n  - name: admin\n    description: Super admin methods\n  - name: internal\nservers:\n  - url: \"https://my.super.server.com/v1\"\npaths:\n  \"/hello/world/{paramTest}\":\n    summary: Some test group of requests\n    description: Another test description\n    get:\n      tags:\n        - internal\n      summary: Small summary\n      description: Small description\n      deprecated: true\n      responses:\n        200:\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: string\n        418:\n          description: Optional response description\n          content:\n            application/json:\n              schema:\n                type: string\n      parameters:\n        - name: someParam\n          description: Test\n          in: query\n          schema:\n            type: integer\n            format: uint32\n    post:\n      tags:\n        - admin\n      security:\n        - bearerAuth: []\n      requestBody:\n        required: true\n        description: Some interesting description\n        content:\n          application/json:\n            schema:\n              $ref: \"#/components/schemas/GenericStructWithRef\"\n      responses:\n        200:\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: \"#/components/schemas/SuperResponse\"\n      callbacks:\n        callbackUrl:\n          /callbackUrl:\n            post:\n              responses:\n                200:\n                  description: OK\n                  content:\n                    application/json:\n                      schema:\n                        type: array\n                        items:\n                          type: string\n    parameters:\n      - name: paramTest\n        in: path\n        required: true\n        schema:\n          type: string\n      - name: x-request-id\n        description: Test\n        in: header\n        required: true\n        schema:\n          type: string\ncomponents:\n  schemas:\n    AdjacentlyTaggedEnum:\n      type: object\n      properties:\n        content:\n          oneOf:\n            - type: string\n            - type: array\n              items:\n                oneOf:\n                  - $ref: \"#/components/schemas/NewType\"\n                  - $ref: \"#/components/schemas/NewType\"\n        tag:\n          description: AdjacentlyTaggedEnum type variant\n          type: string\n          enum:\n            - first\n            - second\n          example: first\n      required:\n        - tag\n        - content\n    ExternallyTaggedEnum:\n      type: object\n      additionalProperties:\n        oneOf:\n          - type: string\n          - type: array\n            items:\n              oneOf:\n                - type: string\n                - description: Second\n                  type: string\n    GenericStructWithRef:\n      type: object\n      properties:\n        message:\n          type: string\n        test:\n          type: integer\n          format: int64\n      required:\n        - message\n        - test\n    InternallyTaggedEnum:\n      oneOf:\n        - type: object\n          properties:\n            first_field:\n              type: integer\n              format: int32\n            second:\n              description: Field description\n              type: string\n            tag:\n              description: InternallyTaggedEnum type variant\n              type: string\n              enum:\n                - first\n              example: first\n          required:\n            - first_field\n            - second\n            - tag\n        - type: object\n          properties:\n            field:\n              type: string\n            tag:\n              description: InternallyTaggedEnum type variant\n              type: string\n              enum:\n                - second\n              example: second\n          required:\n            - field\n            - tag\n    NewType:\n      description: newtype string\n      type: string\n      format: id\n      example: abcd0001\n    SimpleEnum:\n      description: Simple enum\n      type: string\n      enum:\n        - test\n        - another\n        - yay\n      example: test\n    StructWithComplexObjects:\n      type: object\n      properties:\n        boxed:\n          nullable: true\n          type: integer\n          format: int32\n        field:\n          nullable: true\n          type: string\n        super_optional:\n          nullable: true\n          type: string\n      required:\n        - field\n        - boxed\n    SuperResponse:\n      type: object\n      properties:\n        adjacently_tagged_enum:\n          $ref: \"#/components/schemas/AdjacentlyTaggedEnum\"\n        externally_tagged_enum:\n          $ref: \"#/components/schemas/ExternallyTaggedEnum\"\n        internally_tagged_enum:\n          $ref: \"#/components/schemas/InternallyTaggedEnum\"\n        new_type:\n          $ref: \"#/components/schemas/NewType\"\n        simple_enum:\n          $ref: \"#/components/schemas/SimpleEnum\"\n        struct_with_complex_objects:\n          $ref: \"#/components/schemas/StructWithComplexObjects\"\n        type_changed_struct:\n          $ref: \"#/components/schemas/TypeChangedStruct\"\n        untagged_enum:\n          $ref: \"#/components/schemas/UntaggedEnum\"\n      required:\n        - simple_enum\n        - new_type\n        - externally_tagged_enum\n        - untagged_enum\n        - internally_tagged_enum\n        - adjacently_tagged_enum\n        - type_changed_struct\n        - struct_with_complex_objects\n    TypeChangedStruct:\n      type: object\n      properties:\n        timestamp:\n          description: UTC timestamp in milliseconds\n          type: integer\n          format: int64\n      required:\n        - timestamp\n    UntaggedEnum:\n      oneOf:\n        - type: object\n          properties:\n            value:\n              $ref: \"#/components/schemas/NewType\"\n          required:\n            - value\n        - description: Variant description\n          type: object\n          properties:\n            another:\n              description: Inlined struct\n              type: object\n              properties:\n                first_field:\n                  type: integer\n                  format: int32\n                second:\n                  description: Field description\n                  type: string\n              required:\n                - first_field\n                - second\n          required:\n            - another\n  securitySchemes:\n    bearerAuth:\n      type: http\n      scheme: bearer\n      bearerFormat: JWT\n```\n\u003c/p\u003e\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frexagon%2Fopg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frexagon%2Fopg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frexagon%2Fopg/lists"}