-
-
Notifications
You must be signed in to change notification settings - Fork 7.4k
[kotlin][jvm-okhttp4] Fix multipart/form-data with JSON content-type #22856
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| openapi: 3.0.0 | ||
| servers: | ||
| - url: 'http://localhost:3000/' | ||
| info: | ||
| version: 1.0.0 | ||
| title: Echo API for Kotlin Multipart JSON Test | ||
| description: Echo server API to test multipart/form-data with JSON content-type | ||
| license: | ||
| name: Apache-2.0 | ||
| url: 'https://www.apache.org/licenses/LICENSE-2.0.html' | ||
| tags: | ||
| - name: body | ||
| description: Test body operations | ||
| paths: | ||
| /body/multipart/formdata/with_json_part: | ||
| post: | ||
| tags: | ||
| - body | ||
| summary: Test multipart with JSON part | ||
| description: Test multipart/form-data with a part that has Content-Type application/json | ||
| operationId: testBodyMultipartFormdataWithJsonPart | ||
| requestBody: | ||
| required: true | ||
| content: | ||
| multipart/form-data: | ||
| schema: | ||
| type: object | ||
| required: | ||
| - metadata | ||
| - file | ||
| properties: | ||
| metadata: | ||
| $ref: '#/components/schemas/FileMetadata' | ||
| file: | ||
| type: string | ||
| format: binary | ||
| description: File to upload | ||
| encoding: | ||
| metadata: | ||
| contentType: application/json | ||
| file: | ||
| contentType: image/jpeg | ||
| responses: | ||
| '200': | ||
| description: Successful operation | ||
| content: | ||
| text/plain: | ||
| schema: | ||
| type: string | ||
| components: | ||
| schemas: | ||
| FileMetadata: | ||
| type: object | ||
| required: | ||
| - id | ||
| - name | ||
| properties: | ||
| id: | ||
| type: integer | ||
| format: int64 | ||
| example: 12345 | ||
| name: | ||
| type: string | ||
| example: test-file | ||
| tags: | ||
| type: array | ||
| items: | ||
| type: string | ||
| example: ["tag1", "tag2"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # OpenAPI Generator Ignore | ||
| # Generated by openapi-generator https://github.com/openapitools/openapi-generator | ||
|
|
||
| # Use this file to prevent files from being overwritten by the generator. | ||
| # The patterns follow closely to .gitignore or .dockerignore. | ||
|
|
||
| # As an example, the C# client generator defines ApiClient.cs. | ||
| # You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: | ||
| #ApiClient.cs | ||
|
|
||
| # You can match any string of characters against a directory, file or extension with a single asterisk (*): | ||
| #foo/*/qux | ||
| # The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux | ||
|
|
||
| # You can recursively match patterns against a directory, file or extension with a double asterisk (**): | ||
| #foo/**/qux | ||
| # This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux | ||
|
|
||
| # You can also negate patterns with an exclamation (!). | ||
| # For example, you can ignore all files in a docs folder with the file extension .md: | ||
| #docs/*.md | ||
| # Then explicitly reverse the ignore rule for a single file: | ||
| #!docs/README.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| README.md | ||
| build.gradle | ||
| docs/BodyApi.md | ||
| docs/FileMetadata.md | ||
| gradle/wrapper/gradle-wrapper.jar | ||
| gradle/wrapper/gradle-wrapper.properties | ||
| gradlew | ||
| gradlew.bat | ||
| settings.gradle | ||
| src/main/kotlin/org/openapitools/client/apis/BodyApi.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/PartConfig.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt | ||
| src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt | ||
| src/main/kotlin/org/openapitools/client/models/FileMetadata.kt |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 7.20.0-SNAPSHOT |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| # org.openapitools.client - Kotlin client library for Echo API for Kotlin Multipart JSON Test | ||
|
|
||
| Echo server API to test multipart/form-data with JSON content-type | ||
|
|
||
| ## Overview | ||
| This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [openapi-spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate an API client. | ||
|
|
||
| - API version: 1.0.0 | ||
| - Package version: | ||
| - Generator version: 7.20.0-SNAPSHOT | ||
| - Build package: org.openapitools.codegen.languages.KotlinClientCodegen | ||
|
|
||
| ## Requires | ||
|
|
||
| * Kotlin 2.2.20 | ||
| * Gradle 8.14 | ||
|
|
||
| ## Build | ||
|
|
||
| First, create the gradle wrapper script: | ||
|
|
||
| ``` | ||
| gradle wrapper | ||
| ``` | ||
|
|
||
| Then, run: | ||
|
|
||
| ``` | ||
| ./gradlew check assemble | ||
| ``` | ||
|
|
||
| This runs all tests and packages the library. | ||
|
|
||
| ## Features/Implementation Notes | ||
|
|
||
| * Supports JSON inputs/outputs, File inputs, and Form inputs. | ||
| * Supports collection formats for query parameters: csv, tsv, ssv, pipes. | ||
| * Some Kotlin and Java types are fully qualified to avoid conflicts with types defined in OpenAPI definitions. | ||
| * Implementation of ApiClient is intended to reduce method counts, specifically to benefit Android targets. | ||
|
|
||
| <a id="documentation-for-api-endpoints"></a> | ||
| ## Documentation for API Endpoints | ||
|
|
||
| All URIs are relative to *http://localhost:3000* | ||
|
|
||
| | Class | Method | HTTP request | Description | | ||
| | ------------ | ------------- | ------------- | ------------- | | ||
| | *BodyApi* | [**testBodyMultipartFormdataWithJsonPart**](docs/BodyApi.md#testbodymultipartformdatawithjsonpart) | **POST** /body/multipart/formdata/with_json_part | Test multipart with JSON part | | ||
|
|
||
|
|
||
| <a id="documentation-for-models"></a> | ||
| ## Documentation for Models | ||
|
|
||
| - [org.openapitools.client.models.FileMetadata](docs/FileMetadata.md) | ||
|
|
||
|
|
||
| <a id="documentation-for-authorization"></a> | ||
| ## Documentation for Authorization | ||
|
|
||
| Endpoints do not require authorization. | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| group 'org.openapitools' | ||
| version '1.0.0' | ||
|
|
||
| wrapper { | ||
| gradleVersion = '8.14.3' | ||
| distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip" | ||
| } | ||
|
|
||
| buildscript { | ||
| ext.kotlin_version = '2.2.20' | ||
| ext.spotless_version = "7.2.1" | ||
|
|
||
| repositories { | ||
| maven { url "https://repo1.maven.org/maven2" } | ||
| } | ||
| dependencies { | ||
| classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | ||
| classpath "com.diffplug.spotless:spotless-plugin-gradle:$spotless_version" | ||
| } | ||
| } | ||
|
|
||
| apply plugin: 'kotlin' | ||
| apply plugin: 'maven-publish' | ||
| apply plugin: 'com.diffplug.spotless' | ||
|
|
||
| repositories { | ||
| maven { url "https://repo1.maven.org/maven2" } | ||
| } | ||
|
|
||
| // Use spotless plugin to automatically format code, remove unused import, etc | ||
| // To apply changes directly to the file, run `gradlew spotlessApply` | ||
| // Ref: https://github.com/diffplug/spotless/tree/main/plugin-gradle | ||
| spotless { | ||
| // comment out below to run spotless as part of the `check` task | ||
| enforceCheck false | ||
|
|
||
| format 'misc', { | ||
| // define the files (e.g. '*.gradle', '*.md') to apply `misc` to | ||
| target '.gitignore' | ||
|
|
||
| // define the steps to apply to those files | ||
| trimTrailingWhitespace() | ||
| indentWithSpaces() // Takes an integer argument if you don't like 4 | ||
| endWithNewline() | ||
| } | ||
| kotlin { | ||
| ktfmt() | ||
| } | ||
| } | ||
|
|
||
| test { | ||
| useJUnitPlatform() | ||
| } | ||
|
|
||
| dependencies { | ||
| implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" | ||
| implementation "com.google.code.gson:gson:2.13.2" | ||
| implementation "com.squareup.okhttp3:okhttp:5.1.0" | ||
| testImplementation "io.kotlintest:kotlintest-runner-junit5:3.4.2" | ||
| } | ||
|
|
||
| java { | ||
| withSourcesJar() | ||
| } | ||
|
|
||
| publishing { | ||
| publications { | ||
| maven(MavenPublication) { | ||
| groupId = 'org.openapitools' | ||
| artifactId = 'kotlin-client' | ||
| version = '1.0.0' | ||
| from components.java | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # BodyApi | ||
|
|
||
| All URIs are relative to *http://localhost:3000* | ||
|
|
||
| | Method | HTTP request | Description | | ||
| | ------------- | ------------- | ------------- | | ||
| | [**testBodyMultipartFormdataWithJsonPart**](BodyApi.md#testBodyMultipartFormdataWithJsonPart) | **POST** /body/multipart/formdata/with_json_part | Test multipart with JSON part | | ||
|
|
||
|
|
||
| <a id="testBodyMultipartFormdataWithJsonPart"></a> | ||
| # **testBodyMultipartFormdataWithJsonPart** | ||
| > kotlin.String testBodyMultipartFormdataWithJsonPart(metadata, file) | ||
|
|
||
| Test multipart with JSON part | ||
|
|
||
| Test multipart/form-data with a part that has Content-Type application/json | ||
|
|
||
| ### Example | ||
| ```kotlin | ||
| // Import classes: | ||
| //import org.openapitools.client.infrastructure.* | ||
| //import org.openapitools.client.models.* | ||
|
|
||
| val apiInstance = BodyApi() | ||
| val metadata : FileMetadata = // FileMetadata | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: The Kotlin example declares Prompt for AI agents |
||
| val file : java.io.File = BINARY_DATA_HERE // java.io.File | File to upload | ||
| try { | ||
| val result : kotlin.String = apiInstance.testBodyMultipartFormdataWithJsonPart(metadata, file) | ||
| println(result) | ||
| } catch (e: ClientException) { | ||
| println("4xx response calling BodyApi#testBodyMultipartFormdataWithJsonPart") | ||
| e.printStackTrace() | ||
| } catch (e: ServerException) { | ||
| println("5xx response calling BodyApi#testBodyMultipartFormdataWithJsonPart") | ||
| e.printStackTrace() | ||
| } | ||
| ``` | ||
|
|
||
| ### Parameters | ||
| | **metadata** | [**FileMetadata**](FileMetadata.md)| | | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: Malformed Markdown table: header/separator rows come after the first data row, so Prompt for AI agents |
||
| | Name | Type | Description | Notes | | ||
| | ------------- | ------------- | ------------- | ------------- | | ||
| | **file** | **java.io.File**| File to upload | | | ||
|
|
||
| ### Return type | ||
|
|
||
| **kotlin.String** | ||
|
|
||
| ### Authorization | ||
|
|
||
| No authorization required | ||
|
|
||
| ### HTTP request headers | ||
|
|
||
| - **Content-Type**: multipart/form-data | ||
| - **Accept**: text/plain | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
|
|
||
| # FileMetadata | ||
|
|
||
| ## Properties | ||
| | Name | Type | Description | Notes | | ||
| | ------------ | ------------- | ------------- | ------------- | | ||
| | **id** | **kotlin.Long** | | | | ||
| | **name** | **kotlin.String** | | | | ||
| | **tags** | **kotlin.collections.List<kotlin.String>** | | [optional] | | ||
|
|
||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| distributionBase=GRADLE_USER_HOME | ||
| distributionPath=wrapper/dists | ||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip | ||
| networkTimeout=10000 | ||
| validateDistributionUrl=true | ||
| zipStoreBase=GRADLE_USER_HOME | ||
| zipStorePath=wrapper/dists |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Multipart JSON parts using Kotlinx Serialization will throw at runtime because
encodeToString(obj)is invoked with type‑erasedAny(no serializer), which requires polymorphic registration.Prompt for AI agents