8000 fix: ref with same id in properties by climba03003 · Pull Request #464 · fastify/fast-json-stringify · GitHub
[go: up one dir, main page]

Skip to content

fix: ref with same id in properties #464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
8000
Loading
Diff view
Diff view
49 changes: 46 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ function mergeLocation (source, dest) {
const arrayItemsReferenceSerializersMap = new Map()
const objectReferenceSerializersMap = new Map()
const schemaReferenceMap = new Map()
const dedupRefsSet = new Set()
let dedupTrack = []

let ajvInstance = null
let contextFunctions = null
Expand All @@ -60,6 +62,8 @@ function build (schema, options) {
arrayItemsReferenceSerializersMap.clear()
objectReferenceSerializersMap.clear()
schemaReferenceMap.clear()
dedupRefsSet.clear()
dedupTrack = []

contextFunctions = []
options = options || {}
Expand Down Expand Up @@ -150,6 +154,8 @@ function build (schema, options) {
arrayItemsReferenceSerializersMap.clear()
objectReferenceSerializersMap.clear()
schemaReferenceMap.clear()
dedupRefsSet.clear()
dedupTrack = []

return stringifyFunc
}
Expand Down Expand Up @@ -253,6 +259,7 @@ function addPatternProperties (location) {
}
`
})

if (schema.additionalProperties) {
code += additionalProperty(location)
}
Expand Down Expand Up @@ -326,7 +333,7 @@ function refFinder (ref, location) {

if (externalSchema && externalSchema[ref]) {
return {
schema: externalSchema[ref],
schema: dedupIdsRefs(ref, externalSchema[ref]),
root: externalSchema[ref],
externalSchema
}
Expand Down Expand Up @@ -447,8 +454,9 @@ function buildCode (location, locationPath) {

Object.keys(schema.properties || {}).forEach((key) => {
let propertyLocation = mergeLocation(location, { schema: schema.properties[key] })
if (schema.properties[key].$ref) {
propertyLocation = refFinder(schema.properties[key].$ref, location)
const ref = schema.properties[key].$ref
if (ref) {
propertyLocation = refFinder(ref, location)
schema.properties[key] = propertyLocation.schema
}

Expand Down Expand Up @@ -595,6 +603,8 @@ function buildInnerObject (location, locationPath) {
}

function addIfThenElse (location, locationPath) {
dedupT 8000 rack.push('ifThenElse')

let code = ''

const schema = location.schema
Expand Down Expand Up @@ -640,6 +650,9 @@ function addIfThenElse (location, locationPath) {
code += `
}
`

dedupTrack.pop()

return code
}

Expand Down Expand Up @@ -884,6 +897,33 @@ function dereferenceOfRefs (location, type) {
return locations
}

function _dedupIdsRefs (refs, schema) {
// we dedup the same $ref only and clear the $id after the first one.
// so, it can keep track the duplicate $id when it trying to resolve
// difference schema.
// however, it will not works for $id in nested properties.
if (dedupRefsSet.has(refs)) {
// we need to check if we face the recursive schema
if (!objectReferenceSerializersMap.has(schema) && !arrayItemsReferenceSerializersMap.has(schema)) {
schema = clone(schema)
delete schema.$id
}
}

dedupRefsSet.add(refs)

return schema
}

function _dummyDedupIdsRefs (_, schema) {
return schema
}

function dedupIdsRefs (refs, schema) {
// we should ignore the $refs in root schema
return dedupTrack.join(',') === '' ? _dummyDedupIdsRefs(refs, schema) : _dedupIdsRefs(refs, schema)
}

let genFuncNam 9264 eCounter = 0
function generateFuncName () {
return 'anonymous' + genFuncNameCounter++
Expand Down Expand Up @@ -949,6 +989,7 @@ function buildValue (locationPath, input, location) {
break
case undefined:
if (schema.anyOf || schema.oneOf) {
dedupTrack.push(schema.anyOf ? 'anyOf' : 'oneOf')
// beware: dereferenceOfRefs has side effects and changes schema.anyOf
const locations = dereferenceOfRefs(location, schema.anyOf ? 'anyOf' : 'oneOf')
locations.forEach((location, index) => {
Expand Down Expand Up @@ -976,6 +1017,8 @@ function buildValue (locationPath, input, location) {
`
})

dedupTrack.pop()

code += `
else throw new Error(\`The value $\{JSON.stringify(${input})} does not match schema definition.\`)
`
Expand Down
Loading
0