Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ export class {{classname}} extends runtime.BaseAPI {
{{^isEnumRef}}
{{^withoutRuntimeChecks}}
{{^isContainer}}
formParams.append('{{baseName}}', new Blob([JSON.stringify({{{dataType}}}ToJSON(requestParameters['{{paramName}}']))], { type: "application/json", }));
formParams.append('{{baseName}}', new Blob([JSON.stringify({{#isFreeFormObject}}runtime.anyToJSON{{/isFreeFormObject}}{{^isFreeFormObject}}{{{dataType}}}ToJSON{{/isFreeFormObject}}(requestParameters['{{paramName}}']))], { type: "application/json", }));
{{/isContainer}}
{{#isContainer}}
formParams.append('{{baseName}}', new Blob([JSON.stringify(requestParameters['{{paramName}}'])], { type: "application/json", }));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
}
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}
{{/withoutRuntimeChecks}}

export function canConsumeForm(consumes: Consume[]): boolean {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"openapi": "3.0.1",
"info": {
"title": "Any Type Property Test",
"version": "1.0.0"
},
"paths": {
"/upload": {
"post": {
"operationId": "uploadFile",
"tags": ["Upload"],
"requestBody": {
"content": {
"application/x-www-form-urlencoded": {
"schema": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string"
},
"file": {
"type": "object"
}
}
}
}
}
},
"responses": {
"200": {
"description": "Success"
}
}
}
}
},
"components": {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The new anyToJSON helper prevents the reported ReferenceError, but its raw pass-through implementation silently mis-serializes object or array values when they are appended to FormData. FormData.append stringifies non-Blob values via String(value), so an object becomes "[object Object]" instead of a JSON string, which can corrupt multipart payloads at runtime without throwing. Consider using JSON.stringify for non-Blob objects so the function matches its *ToJSON naming and contract, or handling primitives and Blobs explicitly to avoid this silent data loss.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/others/typescript-fetch/additional-properties-in-multipart-issue/runtime.ts, line 371:

<comment>The new `anyToJSON` helper prevents the reported `ReferenceError`, but its raw pass-through implementation silently mis-serializes object or array values when they are appended to `FormData`. `FormData.append` stringifies non-Blob values via `String(value)`, so an object becomes `"[object Object]"` instead of a JSON string, which can corrupt multipart payloads at runtime without throwing. Consider using `JSON.stringify` for non-Blob objects so the function matches its `*ToJSON` naming and contract, or handling primitives and Blobs explicitly to avoid this silent data loss.</comment>

<file context>
@@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
 }
 
+// Pass-through serializer for `any`-typed properties in form data. See #1877.
+export function anyToJSON(value: any): any {
+    return value;
+}
</file context>
Suggested change
export function anyToJSON(value: any): any {
export function anyToJSON(value: any): any {
if (value instanceof Blob) {
return value;
}
if (typeof value === 'object' && value !== null) {
return JSON.stringify(value);
}
return value;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review!
anyToJSON is always called wrapped in JSON.stringify(anyToJSON(value)) in the generated code, so a plain pass-through is correct — adding JSON.stringify inside would cause double serialization.

return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ export function mapValues(data: any, fn: (item: any) => any) {
return result;
}

// Pass-through serializer for `any`-typed properties in form data. See #1877.
export function anyToJSON(value: any): any {
return value;
}

export function canConsumeForm(consumes: Consume[]): boolean {
for (const consume of consumes) {
if (consume.contentType?.startsWith('multipart/form-data') == true) {
Expand Down
12 changes: 8 additions & 4 deletions samples/server/petstore/jaxrs-spec-enum/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.6</version>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.6</version>
<version>3.5.6</version>
<executions>
<execution>
<goals>
Expand Down Expand Up @@ -91,8 +95,8 @@
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
Expand Down Expand Up @@ -135,7 +139,7 @@
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jackson-version>2.19.2</jackson-version>
<junit-version>4.13.2</junit-version>
<junit-version>5.14.4</junit-version>
<joda-version>2.10.13</joda-version>
<javax.annotation-api-version>1.3.2</javax.annotation-api-version>
<beanvalidation-version>2.0.2</beanvalidation-version>
Expand Down
Loading