@@ -228,6 +228,10 @@ function getStringSerializer (format) {
228228 '$asString'
229229}
230230
231+ function getTestSerializer ( format ) {
232+ return stringSerializerMap [ format ]
233+ }
234+
231235function $pad2Zeros ( num ) {
232236 const s = '00' + num
233237 return s [ s . length - 2 ] + s [ s . length - 1 ]
@@ -280,37 +284,40 @@ function $asBooleanNullable (bool) {
280284 return bool === null ? null : $asBoolean ( bool )
281285}
282286
283- function $asDatetime ( date ) {
287+ function $asDatetime ( date , skipQuotes ) {
288+ const quotes = skipQuotes === true ? '' : '"'
284289 if ( date instanceof Date ) {
285- return '"' + date . toISOString ( ) + '"'
290+ return quotes + date . toISOString ( ) + quotes
286291 } else if ( date && typeof date . toISOString === 'function' ) {
287- return '"' + date . toISOString ( ) + '"'
292+ return quotes + date . toISOString ( ) + quotes
288293 } else {
289294 return $asString ( date )
290295 }
291296}
292297
293- function $asDate ( date ) {
298+ function $asDate ( date , skipQuotes ) {
299+ const quotes = skipQuotes === true ? '' : '"'
294300 if ( date instanceof Date ) {
295301 const year = new Intl . DateTimeFormat ( 'en' , { year : 'numeric' } ) . format ( date )
296302 const month = new Intl . DateTimeFormat ( 'en' , { month : '2-digit' } ) . format ( date )
297303 const day = new Intl . DateTimeFormat ( 'en' , { day : '2-digit' } ) . format ( date )
298- return '"' + year + '-' + month + '-' + day + '"'
304+ return quotes + year + '-' + month + '-' + day + quotes
299305 } else if ( date && typeof date . format === 'function' ) {
300- return '"' + date . format ( 'YYYY-MM-DD' ) + '"'
306+ return quotes + date . format ( 'YYYY-MM-DD' ) + quotes
301307 } else {
302308 return $asString ( date )
303309 }
304310}
305311
306- function $asTime ( date ) {
312+ function $asTime ( date , skipQuotes ) {
313+ const quotes = skipQuotes === true ? '' : '"'
307314 if ( date instanceof Date ) {
308315 const hour = new Intl . DateTimeFormat ( 'en' , { hour : 'numeric' , hour12 : false } ) . format ( date )
309316 const minute = new Intl . DateTimeFormat ( 'en' , { minute : 'numeric' } ) . format ( date )
310317 const second = new Intl . DateTimeFormat ( 'en' , { second : 'numeric' } ) . format ( date )
311- return '"' + $pad2Zeros ( hour ) + ':' + $pad2Zeros ( minute ) + ':' + $pad2Zeros ( second ) + '"'
318+ return quotes + $pad2Zeros ( hour ) + ':' + $pad2Zeros ( minute ) + ':' + $pad2Zeros ( second ) + quotes
312319 } else if ( date && typeof date . format === 'function' ) {
313- return '"' + date . format ( 'HH:mm:ss' ) + '"'
320+ return quotes + date . format ( 'HH:mm:ss' ) + quotes
314321 } else {
315322 return $asString ( date )
316323 }
@@ -1177,6 +1184,11 @@ function nested (laterCode, name, key, location, subKey, isArray) {
11771184 const anyOfLocations = dereferenceOfRefs ( location , 'anyOf' )
11781185 anyOfLocations . forEach ( ( location , index ) => {
11791186 const nestedResult = nested ( laterCode , name , key , location , subKey !== '' ? subKey : 'i' + index , isArray )
1187+ // We need a test serializer as the String serializer will not work with
1188+ // date/time ajv validations
1189+ // see: https://github.com/fastify/fast-json-stringify/issues/325
1190+ const testSerializer = getTestSerializer ( location . schema . format )
1191+ const testValue = testSerializer !== undefined ? `${ testSerializer } (obj${ accessor } , true)` : `obj${ accessor } `
11801192
11811193 // Since we are only passing the relevant schema to ajv.validate, it needs to be full dereferenced
11821194 // otherwise any $ref pointing to an external schema would result in an error.
@@ -1186,7 +1198,7 @@ function nested (laterCode, name, key, location, subKey, isArray) {
11861198 // 2. `nested`, through `buildCode`, replaces any reference in object properties with the actual schema
11871199 // (see https://github.com/fastify/fast-json-stringify/blob/6da3b3e8ac24b1ca5578223adedb4083b7adf8db/index.js#L631)
11881200 code += `
1189- ${ index === 0 ? 'if' : 'else if' } (ajv.validate(${ JSON . stringify ( location . schema ) } , obj ${ accessor } ))
1201+ ${ index === 0 ? 'if' : 'else if' } (ajv.validate(${ JSON . stringify ( location . schema ) } , ${ testValue } ))
11901202 ${ nestedResult . code }
11911203 `
11921204 laterCode = nestedResult . laterCode
@@ -1199,10 +1211,11 @@ function nested (laterCode, name, key, location, subKey, isArray) {
11991211 const oneOfLocations = dereferenceOfRefs ( location , 'oneOf' )
12001212 oneOfLocations . forEach ( ( location , index ) => {
12011213 const nestedResult = nested ( laterCode , name , key , location , subKey !== '' ? subKey : 'i' + index , isArray )
1202-
1203- // see comment on anyOf about derefencing the schema before calling ajv.validate
1214+ const testSerializer = getTestSerializer ( location . schema . format )
1215+ const testValue = testSerializer !== undefined ? `${ testSerializer } (obj${ accessor } , true)` : `obj${ accessor } `
1216+ // see comment on anyOf about dereferencing the schema before calling ajv.validate
12041217 code += `
1205- ${ index === 0 ? 'if' : 'else if' } (ajv.validate(${ JSON . stringify ( location . schema ) } , obj ${ accessor } ))
1218+ ${ index === 0 ? 'if' : 'else if' } (ajv.validate(${ JSON . stringify ( location . schema ) } , ${ testValue } ))
12061219 ${ nestedResult . code }
12071220 `
12081221 laterCode = nestedResult . laterCode
0 commit comments