Repository navigation
fix(java): serialize jersey multipart object parts as JSON and honor … - #25120
MatteoMolinari93 wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
18 issues found across 31 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="samples/openapi3/client/petstore/java/jersey2-java8-special-characters/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/openapi3/client/petstore/java/jersey2-java8-special-characters/src/main/java/org/openapitools/client/ApiClient.java:916">
P2: The complex-object fallback ignores the declared multipart content type and always emits `application/json`. Preserve the JSON serialization if intended, but use `partType` when it is declared so per-part `encoding.contentType` is honored.</violation>
</file>
<file name="samples/openapi3/client/petstore/java/jersey2-java8-swagger2/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/openapi3/client/petstore/java/jersey2-java8-swagger2/src/main/java/org/openapitools/client/ApiClient.java:1041">
P2: This branch overrides a declared non-JSON part content type for complex values and sends `Content-Type: application/json`, so the new encoding metadata is not honored for those valid multipart parts. Preserve the declared `partType` when it is present, using JSON only as the fallback when no part type was declared.</violation>
</file>
<file name="samples/client/petstore/java/jersey3-jackson3/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/petstore/java/jersey3-jackson3/src/main/java/org/openapitools/client/ApiClient.java:1140">
P2: This fallback discards a declared non-JSON `partType` for complex values, so the multipart part advertises `application/json` instead of the encoding's type. Use the declared type when present and JSON only when no type was declared.</violation>
<violation number="2" location="samples/client/petstore/java/jersey3-jackson3/src/main/java/org/openapitools/client/ApiClient.java:1140">
P2: When the encoding declares a non-JSON per-part content type for a complex object part (e.g. `application/xml` or `text/csv`), this branch ignores `partType` entirely and always sends the part with `Content-Type: application/json`. The declared encoding is therefore not honored on the wire, and the part header silently contradicts the spec. Either apply the declared `partType` when it is supported, or throw an `ApiException` for declared types the serializer cannot produce, instead of mislabeling the part as JSON.</violation>
</file>
<file name="samples/client/others/java/jersey2-oneOf-Mixed/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/others/java/jersey2-oneOf-Mixed/src/main/java/org/openapitools/client/ApiClient.java:916">
P2: This fallback discards a declared non-JSON `partType` for complex values and always labels the JSON text as `application/json`. Preserve `partType` when it is present, using `application/json` only when no type was declared.</violation>
</file>
<file name="samples/client/petstore/java/jersey3-oneOf/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/petstore/java/jersey3-oneOf/src/main/java/org/openapitools/client/ApiClient.java:917">
P1: This branch ignores the declared content type for complex multipart values, so `encoding` cannot be honored for non-JSON types. Keep JSON serialization if needed, but pass the non-null `partType` to `FormDataBodyPart` instead of always using `MediaType.APPLICATION_JSON_TYPE`.</violation>
</file>
<file name="samples/client/petstore/java/jersey2-java8-localdatetime/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/petstore/java/jersey2-java8-localdatetime/src/main/java/org/openapitools/client/ApiClient.java:1057">
P2: The complex-value fallback ignores a declared non-JSON `partType` and sends the part as `application/json`, so multipart encodings such as `application/xml` are not honored. Use the declared `partType` for the body part when present, while retaining JSON as the fallback only when it is absent.</violation>
</file>
<file name="modules/openapi-generator/src/main/resources/Java/libraries/jersey3/ApiClient.mustache">
<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/jersey3/ApiClient.mustache:1146">
P2: Complex multipart values discard a declared non-JSON encoding and are always labeled `application/json`. Preserve `partType` here, falling back to `application/json` only when no type was declared.</violation>
</file>
<file name="samples/client/petstore/java/jersey3/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/petstore/java/jersey3/src/main/java/org/openapitools/client/ApiClient.java:1140">
P1: Complex multipart values discard the declared `partType`: an encoding such as `application/xml` is serialized as JSON but emitted as `Content-Type: application/json`. Preserve the declared type here so servers parse the part according to the OpenAPI encoding.</violation>
</file>
<file name="modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java">
<violation number="1" location="modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java:5554">
P3: The ApiClient assertions in this test only check text emitted unconditionally by ApiClient.mustache, so they pass for any jersey spec; the only spec-dependent assertion is that `marker` is added to the form params. As written, the test would still pass if a regression serialized the `marker` object via `parameterToString` instead of JSON, so the claim in the comment (`complex parts must be sent as JSON, not via toString()`) is not actually verified. Add a runtime assertion for the object part (e.g., a Jersey client test that sends `marker` and asserts the part is JSON) or narrow the comment to what the static checks actually pin down.</violation>
</file>
<file name="samples/openapi3/client/extensions/x-auth-id-alias/java/jersey2-java8/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/openapi3/client/extensions/x-auth-id-alias/java/jersey2-java8/src/main/java/org/openapitools/client/ApiClient.java:965">
P2: Complex multipart values ignore a declared non-JSON content type and are always sent as `application/json`. Preserve the declared `partType` for this branch (while retaining JSON as the default when no type is declared).</violation>
</file>
<file name="samples/openapi3/client/petstore/java/jersey2-java8-swagger1/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/openapi3/client/petstore/java/jersey2-java8-swagger1/src/main/java/org/openapitools/client/ApiClient.java:1041">
P2: This fallback discards a declared non-JSON encoding for complex values and labels the JSON text as `application/json`. Preserve the declared `partType` when present, using `application/json` only when no type was declared.</violation>
</file>
<file name="samples/openapi3/client/petstore/java/jersey2-java8/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/openapi3/client/petstore/java/jersey2-java8/src/main/java/org/openapitools/client/ApiClient.java:1139">
P2: `addParamToMultipart` discards the declared `partType` for complex values and hardcodes `application/json`. Preserve the declared media type here, or fail explicitly when the value cannot be serialized for that type.</violation>
<violation number="2" location="samples/openapi3/client/petstore/java/jersey2-java8/src/main/java/org/openapitools/client/ApiClient.java:1139">
P3: For complex objects the declared per-part content type is discarded: this branch hardcodes `MediaType.APPLICATION_JSON_TYPE` even when `partType` was parsed from `encoding` and is not a JSON type (e.g. `text/plain`, `application/xml`). That contradicts the new javadoc on `addParamToMultipart` ("The declared part type … takes precedence") and means encoding-based content types are only honored for scalars, files, and JSON types. If the intent is to always send complex parts as JSON, use the declared type only when it is JSON, or apply `partType` as done for the other branches.</violation>
</file>
<file name="samples/client/others/java/jersey2-oneOf-duplicates/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/others/java/jersey2-oneOf-duplicates/src/main/java/org/openapitools/client/ApiClient.java:916">
P2: This branch ignores the declared content type for complex parts. An object or array encoded with a non-JSON type is sent with `application/json`, so the server cannot honor the OpenAPI multipart encoding; retain the declared type when present and use JSON only as the default.</violation>
</file>
<file name="samples/client/petstore/java/jersey2-java8/src/main/java/org/openapitools/client/ApiClient.java">
<violation number="1" location="samples/client/petstore/java/jersey2-java8/src/main/java/org/openapitools/client/ApiClient.java:1057">
P2: The complex-value fallback discards the declared `partType`, so multipart encodings such as `text/plain` or `application/xml` still receive `application/json`. Preserve the declared type for this branch, while retaining JSON as the fallback when no type is declared.</violation>
</file>
<file name="modules/openapi-generator/src/main/resources/Java/libraries/jersey2/ApiClient.mustache">
<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/jersey2/ApiClient.mustache:1140">
P2: This fallback ignores a declared non-JSON `partType`, so complex multipart values are always labeled `application/json` even when the request-body encoding specifies another content type. Use the declared type when present and retain `application/json` only as the fallback.</violation>
<violation number="2" location="modules/openapi-generator/src/main/resources/Java/libraries/jersey2/ApiClient.mustache:1140">
P3: In the complex-object branch of `addParamToMultipart`, a declared non-JSON part content type is silently replaced with `application/json`. A complex part with `encoding: { field: { contentType: text/xml } }` (or `application/x-custom`) is emitted as a JSON body tagged `application/json`, so the declared per-part content type from `encoding` is not honored — which contradicts the PR's stated goal. Use the declared type when present and only fall back to `application/json` when `partType` is null.</violation>
</file>
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
Re-trigger cubic
| // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output | ||
| FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build(); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value))); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); |
There was a problem hiding this comment.
P1: This branch ignores the declared content type for complex multipart values, so encoding cannot be honored for non-JSON types. Keep JSON serialization if needed, but pass the non-null partType to FormDataBodyPart instead of always using MediaType.APPLICATION_JSON_TYPE.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/java/jersey3-oneOf/src/main/java/org/openapitools/client/ApiClient.java, line 917:
<comment>This branch ignores the declared content type for complex multipart values, so `encoding` cannot be honored for non-JSON types. Keep JSON serialization if needed, but pass the non-null `partType` to `FormDataBodyPart` instead of always using `MediaType.APPLICATION_JSON_TYPE`.</comment>
<file context>
@@ -843,27 +864,124 @@ public Entity<?> serialize(Object obj, Map<String, Object> formParams, String co
+ // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value)));
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE));
}
+ }
</file context>
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); | |
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), partType == null ? MediaType.APPLICATION_JSON_TYPE : partType)); |
| // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output | ||
| FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build(); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value))); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); |
There was a problem hiding this comment.
P1: Complex multipart values discard the declared partType: an encoding such as application/xml is serialized as JSON but emitted as Content-Type: application/json. Preserve the declared type here so servers parse the part according to the OpenAPI encoding.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/java/jersey3/src/main/java/org/openapitools/client/ApiClient.java, line 1140:
<comment>Complex multipart values discard the declared `partType`: an encoding such as `application/xml` is serialized as JSON but emitted as `Content-Type: application/json`. Preserve the declared type here so servers parse the part according to the OpenAPI encoding.</comment>
<file context>
@@ -1066,27 +1087,124 @@ public Entity<?> serialize(Object obj, Map<String, Object> formParams, String co
+ // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value)));
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE));
+ }
+ }
</file context>
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); | |
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), partType == null ? MediaType.APPLICATION_JSON_TYPE : partType)); |
| // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output | ||
| FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build(); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value))); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); |
There was a problem hiding this comment.
P2: The complex-object fallback ignores the declared multipart content type and always emits application/json. Preserve the JSON serialization if intended, but use partType when it is declared so per-part encoding.contentType is honored.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/openapi3/client/petstore/java/jersey2-java8-special-characters/src/main/java/org/openapitools/client/ApiClient.java, line 916:
<comment>The complex-object fallback ignores the declared multipart content type and always emits `application/json`. Preserve the JSON serialization if intended, but use `partType` when it is declared so per-part `encoding.contentType` is honored.</comment>
<file context>
@@ -839,30 +860,127 @@ public Entity<?> serialize(Object obj, Map<String, Object> formParams, String co
+ // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value)));
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE));
+ }
+ }
</file context>
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); | |
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), partType == null ? MediaType.APPLICATION_JSON_TYPE : partType)); |
| // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output | ||
| FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build(); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value))); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); |
There was a problem hiding this comment.
P2: This branch overrides a declared non-JSON part content type for complex values and sends Content-Type: application/json, so the new encoding metadata is not honored for those valid multipart parts. Preserve the declared partType when it is present, using JSON only as the fallback when no part type was declared.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/openapi3/client/petstore/java/jersey2-java8-swagger2/src/main/java/org/openapitools/client/ApiClient.java, line 1041:
<comment>This branch overrides a declared non-JSON part content type for complex values and sends `Content-Type: application/json`, so the new encoding metadata is not honored for those valid multipart parts. Preserve the declared `partType` when it is present, using JSON only as the fallback when no part type was declared.</comment>
<file context>
@@ -964,30 +985,127 @@ public Entity<?> serialize(Object obj, Map<String, Object> formParams, String co
+ // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value)));
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE));
+ }
+ }
</file context>
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); | |
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), partType == null ? MediaType.APPLICATION_JSON_TYPE : partType)); |
There was a problem hiding this comment.
Not applying the suggestion. This branch always produces JSON via Jackson. The jersey clients have no XML/CSV/other serializer for multipart parts, so labelling the part with a declared non-JSON type (e.g. application/xml) would make the header contradict the bytes on the wire. JSON-family types (application/json, *+json) are already honoured by the isJsonPartType branch, and files and plain values use the declared type. Throwing instead would turn requests that work today into errors, so I'd rather not do that in this PR. The javadoc wrongly claimed the declared type "takes precedence"; it now describes the actual behaviour, and the branch has a comment explaining why. The same applies to the generated samples.
| // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output | ||
| FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build(); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value))); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); |
There was a problem hiding this comment.
P2: This fallback discards a declared non-JSON partType for complex values, so the multipart part advertises application/json instead of the encoding's type. Use the declared type when present and JSON only when no type was declared.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/java/jersey3-jackson3/src/main/java/org/openapitools/client/ApiClient.java, line 1140:
<comment>This fallback discards a declared non-JSON `partType` for complex values, so the multipart part advertises `application/json` instead of the encoding's type. Use the declared type when present and JSON only when no type was declared.</comment>
<file context>
@@ -1066,27 +1087,124 @@ public Entity<?> serialize(Object obj, Map<String, Object> formParams, String co
+ // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value)));
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE));
+ }
+ }
</file context>
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); | |
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), partType == null ? MediaType.APPLICATION_JSON_TYPE : partType)); |
| // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output | ||
| FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build(); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value))); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); |
There was a problem hiding this comment.
P2: This fallback ignores a declared non-JSON partType, so complex multipart values are always labeled application/json even when the request-body encoding specifies another content type. Use the declared type when present and retain application/json only as the fallback.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/main/resources/Java/libraries/jersey2/ApiClient.mustache, line 1140:
<comment>This fallback ignores a declared non-JSON `partType`, so complex multipart values are always labeled `application/json` even when the request-body encoding specifies another content type. Use the declared type when present and retain `application/json` only as the fallback.</comment>
<file context>
@@ -1063,30 +1084,127 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
+ // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value)));
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE));
+ }
+ }
</file context>
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); | |
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), partType == null ? MediaType.APPLICATION_JSON_TYPE : partType)); |
| // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output | ||
| FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build(); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value))); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); |
There was a problem hiding this comment.
P2: When the encoding declares a non-JSON per-part content type for a complex object part (e.g. application/xml or text/csv), this branch ignores partType entirely and always sends the part with Content-Type: application/json. The declared encoding is therefore not honored on the wire, and the part header silently contradicts the spec. Either apply the declared partType when it is supported, or throw an ApiException for declared types the serializer cannot produce, instead of mislabeling the part as JSON.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/client/petstore/java/jersey3-jackson3/src/main/java/org/openapitools/client/ApiClient.java, line 1140:
<comment>When the encoding declares a non-JSON per-part content type for a complex object part (e.g. `application/xml` or `text/csv`), this branch ignores `partType` entirely and always sends the part with `Content-Type: application/json`. The declared encoding is therefore not honored on the wire, and the part header silently contradicts the spec. Either apply the declared `partType` when it is supported, or throw an `ApiException` for declared types the serializer cannot produce, instead of mislabeling the part as JSON.</comment>
<file context>
@@ -1066,27 +1087,124 @@ public Entity<?> serialize(Object obj, Map<String, Object> formParams, String co
+ // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value)));
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE));
+ }
+ }
</file context>
| validateJavaSourceFiles(files); | ||
| assertThat(output.resolve("src/main/java/xyz/abcdef/api/MultipartApi.java")).content() | ||
| .contains("localVarFormParams.put(\"marker\", marker);"); | ||
| // complex parts must be sent as JSON, not via toString() |
There was a problem hiding this comment.
P3: The ApiClient assertions in this test only check text emitted unconditionally by ApiClient.mustache, so they pass for any jersey spec; the only spec-dependent assertion is that marker is added to the form params. As written, the test would still pass if a regression serialized the marker object via parameterToString instead of JSON, so the claim in the comment (complex parts must be sent as JSON, not via toString()) is not actually verified. Add a runtime assertion for the object part (e.g., a Jersey client test that sends marker and asserts the part is JSON) or narrow the comment to what the static checks actually pin down.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java, line 5554:
<comment>The ApiClient assertions in this test only check text emitted unconditionally by ApiClient.mustache, so they pass for any jersey spec; the only spec-dependent assertion is that `marker` is added to the form params. As written, the test would still pass if a regression serialized the `marker` object via `parameterToString` instead of JSON, so the claim in the comment (`complex parts must be sent as JSON, not via toString()`) is not actually verified. Add a runtime assertion for the object part (e.g., a Jersey client test that sends `marker` and asserts the part is JSON) or narrow the comment to what the static checks actually pin down.</comment>
<file context>
@@ -5535,6 +5535,62 @@ public void testArrayPathParamSerializedAsCollection(String library) {
+ validateJavaSourceFiles(files);
+ assertThat(output.resolve("src/main/java/xyz/abcdef/api/MultipartApi.java")).content()
+ .contains("localVarFormParams.put(\"marker\", marker);");
+ // complex parts must be sent as JSON, not via toString()
+ assertThat(output.resolve("src/main/java/xyz/abcdef/invoker/ApiClient.java")).content()
+ .contains("} else if (isPlainFormValue(value)) {")
</file context>
| // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output | ||
| FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build(); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value))); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); |
There was a problem hiding this comment.
P3: In the complex-object branch of addParamToMultipart, a declared non-JSON part content type is silently replaced with application/json. A complex part with encoding: { field: { contentType: text/xml } } (or application/x-custom) is emitted as a JSON body tagged application/json, so the declared per-part content type from encoding is not honored — which contradicts the PR's stated goal. Use the declared type when present and only fall back to application/json when partType is null.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/main/resources/Java/libraries/jersey2/ApiClient.mustache, line 1140:
<comment>In the complex-object branch of `addParamToMultipart`, a declared non-JSON part content type is silently replaced with `application/json`. A complex part with `encoding: { field: { contentType: text/xml } }` (or `application/x-custom`) is emitted as a JSON body tagged `application/json`, so the declared per-part content type from `encoding` is not honored — which contradicts the PR's stated goal. Use the declared type when present and only fall back to `application/json` when `partType` is null.</comment>
<file context>
@@ -1063,30 +1084,127 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
+ // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value)));
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE));
+ }
+ }
</file context>
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); | |
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), partType == null ? MediaType.APPLICATION_JSON_TYPE : partType)); |
| // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output | ||
| FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build(); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value))); | ||
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); |
There was a problem hiding this comment.
P3: For complex objects the declared per-part content type is discarded: this branch hardcodes MediaType.APPLICATION_JSON_TYPE even when partType was parsed from encoding and is not a JSON type (e.g. text/plain, application/xml). That contradicts the new javadoc on addParamToMultipart ("The declared part type … takes precedence") and means encoding-based content types are only honored for scalars, files, and JSON types. If the intent is to always send complex parts as JSON, use the declared type only when it is JSON, or apply partType as done for the other branches.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At samples/openapi3/client/petstore/java/jersey2-java8/src/main/java/org/openapitools/client/ApiClient.java, line 1139:
<comment>For complex objects the declared per-part content type is discarded: this branch hardcodes `MediaType.APPLICATION_JSON_TYPE` even when `partType` was parsed from `encoding` and is not a JSON type (e.g. `text/plain`, `application/xml`). That contradicts the new javadoc on `addParamToMultipart` ("The declared part type … takes precedence") and means encoding-based content types are only honored for scalars, files, and JSON types. If the intent is to always send complex parts as JSON, use the declared type only when it is JSON, or apply `partType` as done for the other branches.</comment>
<file context>
@@ -1062,30 +1083,127 @@ public Entity<?> serialize(Object obj, Map<String, Object> formParams, String co
+ // Complex objects (models, maps, ...) are sent as JSON parts instead of their toString() output
FormDataContentDisposition contentDisp = FormDataContentDisposition.name(key).build();
- multiPart.bodyPart(new FormDataBodyPart(contentDisp, parameterToString(value)));
+ multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE));
+ }
+ }
</file context>
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), MediaType.APPLICATION_JSON_TYPE)); | |
| multiPart.bodyPart(new FormDataBodyPart(contentDisp, serializeToJson(value), partType == null ? MediaType.APPLICATION_JSON_TYPE : partType)); |
Closes #25119
@bbdouglas (2017/07) @sreeshas (2017/08) @jfiala (2017/08) @lukoyanov (2017/09) @cbornet (2017/09) @jeff9finger (2018/01) @karismann (2019/03) @Zomzog (2019/04) @lwlee2608 (2019/10) @martin-mfg (2023/08) @KannaKim (2026/07)
PR checklist
Commit all changed files.
This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
These must match the expectations made by your contribution.
You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example
./bin/generate-samples.sh bin/configs/java*.IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
Summary by cubic
Fixes Jersey
multipart/form-dataserialization so complex parts (objects, arrays) are sent as JSON instead of plain strings, and per-partcontentTypedeclared in the spec'sencodingis honored.serializegains an overload accepting per-part content types; the existing signature delegates with an empty map, so callers are unaffected.encodingdeclarations.multipart-encoding.yamlspec.Written for commit 9ced467. Summary will update on new commits.