Skip to content
This repository was archived by the owner on Jun 30, 2026. It is now read-only.

Commit a4fda52

Browse files
JialinHuang803Copilotv-jiaodi
authored
Fix body parameter accessor to use methodParameterSegments (#3961)
* Fix body parameter accessor to use methodParameterSegments When a @bodyRoot property is nested inside a wrapper model (e.g., as a named property of an anonymous model parameter in ARM templates), the generated serializer call was using the bare property name (stopParameters) instead of the correct accessor path (body.stopParameters). The fix replaces the direct bodyParameter.name lookup with getParamAccessor(), which resolves the accessor expression from methodParameterSegments — consistent with how header and query parameters already work. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update * update changelog --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jiao Di (MSFT) <v-jiaodi@microsoft.com>
1 parent a3f0491 commit a4fda52

13 files changed

Lines changed: 361 additions & 41 deletions

File tree

packages/autorest.typescript/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
## 6.0.70 (2026-05-13)
1+
## 6.0.70 (2026-05-14)
22

3+
- [Bugfix] Fix body parameter accessor to use methodParameterSegments. Please refer to [#3961](https://github.com/Azure/autorest.typescript/pull/3961)
34
- [Feature] Bump TypeSpec dependencies to latest stable. Please refer to [#3959](https://github.com/Azure/autorest.typescript/pull/3959)
45
- [Bugfix] Deduplicate statusCodes in getExpectedStatuses. Please refer to [#3956](https://github.com/Azure/autorest.typescript/pull/3956)
56
- [Feature] Align Azure monorepo package.json metadata with new repository schema across codegen packages. Please refer to [#3950](https://github.com/Azure/autorest.typescript/pull/3950)

packages/rlc-common/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
## 0.53.0 (2026-05-13)
1+
## 0.53.0 (2026-05-14)
22

3+
- [Bugfix] Fix body parameter accessor to use methodParameterSegments. Please refer to [#3961](https://github.com/Azure/autorest.typescript/pull/3961)
34
- [Feature] Bump TypeSpec dependencies to latest stable. Please refer to [#3959](https://github.com/Azure/autorest.typescript/pull/3959)
45
- [Bugfix] Deduplicate statusCodes in getExpectedStatuses. Please refer to [#3956](https://github.com/Azure/autorest.typescript/pull/3956)
56
- [Feature] Align Azure monorepo package.json metadata with new repository schema across codegen packages. Please refer to [#3950](https://github.com/Azure/autorest.typescript/pull/3950)

packages/typespec-test/test/batch_modular/generated/typespec-ts/src/api/operations.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,9 +1030,7 @@ export function _disableNodeSchedulingSend(
10301030
: {}),
10311031
...options.requestOptions?.headers,
10321032
},
1033-
body: !options["body"]
1034-
? options["body"]
1035-
: nodeDisableSchedulingOptionsSerializer(options["body"]),
1033+
body: !options?.body ? options?.body : nodeDisableSchedulingOptionsSerializer(options?.body),
10361034
});
10371035
}
10381036

@@ -1099,7 +1097,7 @@ export function _reimageNodeSend(
10991097
: {}),
11001098
...options.requestOptions?.headers,
11011099
},
1102-
body: !options["body"] ? options["body"] : nodeReimageOptionsSerializer(options["body"]),
1100+
body: !options?.body ? options?.body : nodeReimageOptionsSerializer(options?.body),
11031101
});
11041102
}
11051103

@@ -1165,7 +1163,7 @@ export function _rebootNodeSend(
11651163
: {}),
11661164
...options.requestOptions?.headers,
11671165
},
1168-
body: !options["body"] ? options["body"] : nodeRebootOptionsSerializer(options["body"]),
1166+
body: !options?.body ? options?.body : nodeRebootOptionsSerializer(options?.body),
11691167
});
11701168
}
11711169

@@ -4001,9 +3999,7 @@ export function _terminateJobSend(
40013999
: {}),
40024000
...options.requestOptions?.headers,
40034001
},
4004-
body: !options["body"]
4005-
? options["body"]
4006-
: batchJobTerminateOptionsSerializer(options["body"]),
4002+
body: !options?.body ? options?.body : batchJobTerminateOptionsSerializer(options?.body),
40074003
});
40084004
}
40094005

packages/typespec-test/test/loadtesting_modular/generated/typespec-ts/src/loadTestRun/api/operations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ export function _listMetricsSend(
187187
...operationOptionsToRequestParameters(options),
188188
contentType: "application/json",
189189
headers: { accept: "application/json", ...options.requestOptions?.headers },
190-
body: !options["body"] ? options["body"] : metricRequestPayloadSerializer(options["body"]),
190+
body: !options?.body ? options?.body : metricRequestPayloadSerializer(options?.body),
191191
});
192192
}
193193

packages/typespec-ts/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
## 0.53.0 (2026-05-13)
1+
## 0.53.0 (2026-05-14)
22

3+
- [Bugfix] Fix body parameter accessor to use methodParameterSegments. Please refer to [#3961](https://github.com/Azure/autorest.typescript/pull/3961)
34
- [Feature] Bump TypeSpec dependencies to latest stable. Please refer to [#3959](https://github.com/Azure/autorest.typescript/pull/3959)
45
- [Bugfix] Deduplicate statusCodes in getExpectedStatuses. Please refer to [#3956](https://github.com/Azure/autorest.typescript/pull/3956)
56
- [Feature] Align Azure monorepo package.json metadata with new repository schema across codegen packages. Please refer to [#3950](https://github.com/Azure/autorest.typescript/pull/3950)

packages/typespec-ts/src/modular/helpers/operationHelpers.ts

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,14 +1702,7 @@ function buildBodyParameter(
17021702
}) as string | undefined;
17031703
}
17041704

1705-
const bodyParamName = normalizeName(
1706-
bodyParameter.name,
1707-
NameType.Parameter,
1708-
true
1709-
);
1710-
let bodyNameExpression = bodyParameter.optional
1711-
? `${optionalParamName}["${bodyParamName}"]`
1712-
: bodyParamName;
1705+
let bodyNameExpression = getParamAccessor(bodyParameter, optionalParamName);
17131706

17141707
// Check if body parameter has a client default value with matching type
17151708
const hasClientDefault =
@@ -1723,15 +1716,17 @@ function buildBodyParameter(
17231716
bodyNameExpression = `(${bodyNameExpression} ?? ${formattedDefault})`;
17241717
}
17251718

1726-
// Only apply nullOrUndefinedPrefix if there's no client default value
1727-
// because the default value already handles null/undefined cases
1728-
const nullOrUndefinedPrefix = hasClientDefault
1729-
? ""
1730-
: getPropertySerializationPrefix(
1731-
context,
1732-
bodyParameter,
1733-
bodyParameter.optional ? optionalParamName : undefined
1734-
);
1719+
// Build null guard using bodyNameExpression so it stays consistent with the
1720+
// accessor path (especially for nested body parameters like options?.body?.x).
1721+
// Skip when there's a client default value since it already handles null/undefined.
1722+
const needsNullGuard =
1723+
!hasClientDefault &&
1724+
(bodyParameter.optional ||
1725+
isTypeNullable(bodyParameter.type) ||
1726+
bodyNameExpression.includes("?."));
1727+
const nullOrUndefinedPrefix = needsNullGuard
1728+
? `!${bodyNameExpression}? ${bodyNameExpression}:`
1729+
: "";
17351730

17361731
// For dual-format operations, check the contentType option at runtime
17371732
if (
@@ -2112,6 +2107,9 @@ function getParamAccessor(
21122107
param: SdkHttpParameter,
21132108
optionalParamName: string = "options"
21142109
): string {
2110+
if (param.isGeneratedName) {
2111+
return param.name;
2112+
}
21152113
const methodParamExpr = getMethodParamExpr(param, optionalParamName);
21162114
const clientPrefix = "context.";
21172115
if (methodParamExpr) {
@@ -2141,6 +2139,11 @@ function getMethodParamExpr(
21412139
if (segments.length === 0) {
21422140
return undefined;
21432141
}
2142+
// When there are multiple paths (e.g., a composite body from multiple method
2143+
// params), we cannot resolve a single accessor — fall back to the caller's logic.
2144+
if (segments.length > 1) {
2145+
return undefined;
2146+
}
21442147
const path = segments[0];
21452148
if (!path || path.length < 1) {
21462149
return undefined;

0 commit comments

Comments
 (0)