1+ import { determineTimestampFormat } from "@smithy/core/protocols" ;
12import { NormalizedSchema , SCHEMA } from "@smithy/core/schema" ;
2- import { dateToUtcString , generateIdempotencyToken , LazyJsonString } from "@smithy/core/serde" ;
3+ import { dateToUtcString , generateIdempotencyToken , LazyJsonString , NumericValue } from "@smithy/core/serde" ;
34import { Schema , ShapeSerializer } from "@smithy/types" ;
5+ import { toBase64 } from "@smithy/util-base64" ;
46
57import { SerdeContextConfig } from "../ConfigurableSerdeContext" ;
68import { JsonSettings } from "./JsonCodec" ;
@@ -22,11 +24,25 @@ export class JsonShapeSerializer extends SerdeContextConfig implements ShapeSeri
2224 this . buffer = this . _write ( this . rootSchema , value ) ;
2325 }
2426
27+ /**
28+ * @internal
29+ */
30+ public writeDiscriminatedDocument ( schema : Schema , value : unknown ) : void {
31+ this . write ( schema , value ) ;
32+ if ( typeof this . buffer === "object" ) {
33+ this . buffer . __type = NormalizedSchema . of ( schema ) . getName ( true ) ;
34+ }
35+ }
36+
2537 public flush ( ) : string {
26- if ( this . rootSchema ?. isStructSchema ( ) || this . rootSchema ?. isDocumentSchema ( ) ) {
38+ const { rootSchema } = this ;
39+ this . rootSchema = undefined ;
40+
41+ if ( rootSchema ?. isStructSchema ( ) || rootSchema ?. isDocumentSchema ( ) ) {
2742 const replacer = new JsonReplacer ( ) ;
2843 return replacer . replaceInJson ( JSON . stringify ( this . buffer , replacer . createReplacer ( ) , 0 ) ) ;
2944 }
45+ // non-struct root schema indicates a blob (base64 string) or plain string payload.
3046 return this . buffer ;
3147 }
3248
@@ -73,23 +89,21 @@ export class JsonShapeSerializer extends SerdeContextConfig implements ShapeSeri
7389 return void 0 ;
7490 }
7591
76- if ( ns . isBlobSchema ( ) && ( value instanceof Uint8Array || typeof value === "string" ) ) {
92+ if (
93+ ( ns . isBlobSchema ( ) && ( value instanceof Uint8Array || typeof value === "string" ) ) ||
94+ ( ns . isDocumentSchema ( ) && value instanceof Uint8Array )
95+ ) {
7796 if ( ns === this . rootSchema ) {
7897 return value ;
7998 }
8099 if ( ! this . serdeContext ?. base64Encoder ) {
81- throw new Error ( "Missing base64Encoder in serdeContext" ) ;
100+ return toBase64 ( value ) ;
82101 }
83102 return this . serdeContext ?. base64Encoder ( value ) ;
84103 }
85104
86- if ( ns . isTimestampSchema ( ) && value instanceof Date ) {
87- const options = this . settings . timestampFormat ;
88- const format = options . useTrait
89- ? ns . getSchema ( ) === SCHEMA . TIMESTAMP_DEFAULT
90- ? options . default
91- : ns . getSchema ( ) ?? options . default
92- : options . default ;
105+ if ( ( ns . isTimestampSchema ( ) || ns . isDocumentSchema ( ) ) && value instanceof Date ) {
106+ const format = determineTimestampFormat ( ns , this . settings ) ;
93107 switch ( format ) {
94108 case SCHEMA . TIMESTAMP_DATE_TIME :
95109 return value . toISOString ( ) . replace ( ".000Z" , "Z" ) ;
@@ -124,6 +138,22 @@ export class JsonShapeSerializer extends SerdeContextConfig implements ShapeSeri
124138 }
125139 }
126140
141+ if ( ns . isDocumentSchema ( ) ) {
142+ if ( isObject ) {
143+ const out = Array . isArray ( value ) ? [ ] : ( { } as any ) ;
144+ for ( const [ k , v ] of Object . entries ( value ) ) {
145+ if ( v instanceof NumericValue ) {
146+ out [ k ] = v ;
147+ } else {
148+ out [ k ] = this . _write ( ns , v ) ;
149+ }
150+ }
151+ return out ;
152+ } else {
153+ return structuredClone ( value ) ;
154+ }
155+ }
156+
127157 return value ;
128158 }
129159}
0 commit comments