用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/aws/aws-sdk-net --skill marshalling命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | marshalling |
| description | Maps Smithy protocol traits to generated SDK marshaller/unmarshaller code patterns |
Under Generated/Model/Internal/MarshallTransformations/:
| File | Class | Base/Interface |
|---|---|---|
{Operation}RequestMarshaller.cs | IMarshaller<IRequest, {Operation}Request> | — |
{Operation}ResponseUnmarshaller.cs | JsonResponseUnmarshaller (or protocol equivalent) | Dispatches errors |
{Shape}Marshaller.cs | IRequestMarshaller<{Shape}, JsonMarshallerContext> | Nested structs in request path |
{Shape}Unmarshaller.cs | IJsonUnmarshaller<{Shape}, JsonUnmarshallerContext> | Nested structs in response path |
{Exception}Unmarshaller.cs | IJsonErrorResponseUnmarshaller<{Exception}, JsonUnmarshallerContext> | — |
Singleton patterns differ by file type:
public readonly static {Shape}Marshaller Instance = new {Shape}Marshaller();private static ... _instance = new ...(); plus a public Instance property (and sometimes internal static GetInstance()).All marshallers and unmarshallers should be partial classes.
Every request marshaller sets up:
IRequest request = new DefaultRequest(publicRequest, "Amazon.{ServiceName}");
request.Headers["Content-Type"] = "{content-type}"; // protocol-dependent
request.Headers[Amazon.Util.HeaderKeys.XAmzApiVersion] = "{version}"; // from ServiceShape.ApiVersion
request.HttpMethod = "{method}"; // from @http trait
request.ResourcePath = "{uri}"; // from @http trait, with labels interpolated
Then serializes members based on placement rules, then returns request.
| Smithy trait | Where | SDK pattern |
|---|---|---|
@httpQuery("name") | Query string | request.Parameters.Add("name", StringUtils.FromString(...)) |
@httpLabel | URI segment | Replace {member} in request.ResourcePath |
@httpHeader("name") | Header | request.Headers["name"] = ... |
@httpPrefixHeaders("prefix") | Multiple headers | Loop dict, prefix each key |
@httpPayload | Entire body | Direct stream/string (skips body serialization) |
@httpResponseCode | (response only) | response.HttpStatusCode |
| No HTTP trait | Body | Protocol-specific serialization |
For awsJson1.x and query/ec2Query: all members go in the body (no HTTP binding traits).
| Protocol | Rule |
|---|---|
| restJson1 / awsJson1.x | @jsonName if present, else Smithy member name (camelCase) |
| restXml | @xmlName if present, else Smithy member name (camelCase) |
| query / ec2Query | @ec2QueryName or PascalCase of member name |
For request marshallers if any of the members are marshalled in the body OR marked with @httpPayload you must setup the PooledContentStream like so:
#if !NETFRAMEWORK
request.ContentStream = new PooledContentStream();
using Utf8JsonWriter writer = new Utf8JsonWriter(((PooledContentStream)request.ContentStream).BufferWriter);
#else
using var memoryStream = new MemoryStream();
using Utf8JsonWriter writer = new Utf8JsonWriter(memoryStream);
#endif
if (publicRequest.IsSetFoo())
{
context.Writer.WritePropertyName("foo"); // wire name
context.Writer.WriteStringValue(publicRequest.Foo);
}
WriteStartObject → {Shape}Marshaller.Instance.Marshall(item, context) → WriteEndObjectWriteStartArray → loop items → WriteEndArrayWriteStartObject → loop WritePropertyName(key) + write value → WriteEndObjectAmazon{ServiceName}Exception if null/empty before serializationAt the end of the request marshaller after flushing the writer write:
#if NETFRAMEWORK
request.Content = memoryStream.ToArray();
#endif
For structure marshallers loop through the structures members and use the rules laid out in Type → Marshal/Unmarshal
xmlWriter.WriteStartElement("MemberName"); // or @xmlName
xmlWriter.WriteValue(publicRequest.Foo);
xmlWriter.WriteEndElement();
@xmlFlattened lists omit the wrapper element@xmlAttribute members become XML attributes on the parent element@xmlNamespace adds xmlns attributerequest.Parameters.Add("MemberName", StringUtils.FromString(publicRequest.Foo));
MemberName.member.{N} (query) or MemberName.{N} (ec2Query)MemberName.entry.{N}.key / MemberName.entry.{N}.valuewhile (context.ReadAtDepth(targetDepth, ref reader))
{
if (context.TestExpression("foo", targetDepth, ref reader))
{
response.Foo = StringUnmarshaller.Instance.Unmarshall(context, ref reader);
continue;
}
}
new JsonListUnmarshaller<T, TUnmarshaller>(TUnmarshaller.Instance)new JsonDictionaryUnmarshaller<K, V, KU, VU>(...)while (context.Read())
{
if (context.TestExpression("MemberName", targetDepth))
{
response.Foo = StringUnmarshaller.Instance.Unmarshall(context);
continue;
}
}
ListName/member| .NET type | JSON Marshal | JSON Unmarshal |
|---|---|---|
string | WriteStringValue | StringUnmarshaller |
int? | WriteNumberValue | IntUnmarshaller |
long? | WriteNumberValue | LongUnmarshaller |
bool? | WriteBooleanValue | BoolUnmarshaller |
float? | WriteNumberValue | FloatUnmarshaller |
double? | WriteNumberValue | DoubleUnmarshaller |
DateTime? | Format-dependent (see below) | DateTimeUnmarshaller |
MemoryStream | WriteStringValue(Convert.ToBase64String(...)) | MemoryStreamUnmarshaller |
List<T> | Array loop | JsonListUnmarshaller<ElementType, ElementUnmarshaller> |
Dictionary<K,V> | Object loop | JsonDictionaryUnmarshaller<K, V, KeyUnmarshaller, ValueUnmarshaller> |
| Structure | {Shape}Marshaller.Instance | {Shape}Unmarshaller.Instance |
An explicit @timestampFormat (on the member or its target) always wins. When unset, the default is
binding-specific, not one per protocol — see the binding-default table below.
@timestampFormat | Marshal (body) | Marshal (header/query/label) |
|---|---|---|
date-time | WriteStringValue(StringUtils.FromDateTimeToISO8601WithOptionalMs(value)) | StringUtils.FromDateTimeToISO8601WithOptionalMs(value) |
http-date | WriteStringValue(StringUtils.FromDateTimeToRFC822(value)) | StringUtils.FromDateTimeToRFC822(value) |
epoch-seconds | WriteNumberValue(System.Convert.ToInt64(StringUtils.FromDateTimeToUnixTimestamp(value.Value))) | StringUtils.FromDateTimeToUnixTimestamp(value) |
restJson1 binding defaults when @timestampFormat is unset (matches the C2J generator's output):
| Binding | Default |
|---|---|
| Body / structure member | epoch-seconds (restJson1's document-timestamp default per the Smithy spec; the generic @timestampFormat default of date-time applies only when a protocol sets none) |
@httpHeader | http-date |
@httpQuery, @httpLabel | date-time |
String forms pass the nullable DateTime? straight to the StringUtils overload; the epoch form
unwraps with .Value.
In {Operation}ResponseUnmarshaller.UnmarshallException:
if (errorResponse.Code != null && errorResponse.Code.Equals("{smithyShapeName}"))
return {Exception}Unmarshaller.Instance.Unmarshall(contextCopy, errorResponse, ref readerCopy);
Error code = Smithy shape name (e.g. "ChannelNotFound"), not the .NET exception name.
Fallback: new Amazon{Service}Exception(errorResponse.Message, ...).
public {Exception} Unmarshall(JsonUnmarshallerContext context, ErrorResponse errorResponse, ref StreamingUtf8JsonReader reader)
{
if (context.Stream.Length > 0) context.Read(ref reader);
var unmarshalledObject = new {Exception}(errorResponse.Message, errorResponse.InnerException,
errorResponse.Type, errorResponse.Code, errorResponse.RequestId, errorResponse.StatusCode);
int targetDepth = context.CurrentDepth;
if (context.Stream.Length > 0)
{
while (context.ReadAtDepth(targetDepth, ref reader))
{
// Additional exception members deserialized here (if any beyond "message")
}
}
return unmarshalledObject;
}
| Concern | restJson1 | awsJson1.x | restXml | query | ec2Query |
|---|---|---|---|---|---|
| Content-Type | application/json | application/x-amz-json-1.{0,1} | (none/xml) | application/x-www-form-urlencoded | application/x-www-form-urlencoded |
| Routing | HTTP method + path | X-Amz-Target: {ServiceName}.{Operation} | HTTP method + path | Action={Operation} param | Action={Operation} param |
| Member placement | HTTP traits | All body | HTTP traits | All body | All body |
| Body format | JSON | JSON | XML | URL-encoded | URL-encoded |
| Timestamp body default | epoch-seconds | epoch-seconds | date-time | date-time | date-time |
| Error code source | JSON code or __type | JSON code or __type | XML <Code> | XML <Code> | XML <Code> |
| Error wrapping | None | None | <ErrorResponse><Error> | <ErrorResponse><Error> | <Response><Errors><Error> |
| Response unmarshaller base | JsonResponseUnmarshaller | JsonResponseUnmarshaller | XmlResponseUnmarshaller | XmlResponseUnmarshaller | XmlResponseUnmarshaller |
Request uses UseQueryString | Yes (for @httpQuery) | No | Yes (for @httpQuery) |
When implementing the next protocol, update this skill with:
| No |
| No |
基于 SOC 职业分类