-
-
Notifications
You must be signed in to change notification settings - Fork 199
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
fix: merged schemas reference resolving #546
Conversation
1530ee3
to
3297481
Compare
index.js
Outdated
schemaId: location.schemaId, | ||
jsonPointer: location.jsonPointer + '/' + key, | ||
isValidated: location.isValidated | ||
class Location { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you evaluate the URL
class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I didn't get you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The URL class has many convenient methods to calculate if the URL is absolute and relative and compose it.
Looking at this Location
class, I have afraid that we are going to replicate the URL
class in future.
So I wanted to point it out to reduce the burden you could face by developing it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think they are the same and URL
is really slow.
The usage here only string
concatenation.
type: 'object', | ||
properties: { | ||
validation: { | ||
$ref: '#/definitions/ValidationFragment' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about an absolute ref like schema:app:foo#/definitions/hello
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, they are working. This PR doesn't change anything for absolute refs. The problem was that when we create merged schema we should have two locations to resolve local refs:
- We need location inside new "merged" schema in case if we have anyof/oneof .., inside merged schema.
- We original location to be able to resolve local reference in this schema, but outside of merged schema.
It's hard to explain simply) #480 Fixed the first case, but broke the second. This PR should support both.
index.js
Outdated
schemaId: location.schemaId, | ||
jsonPointer: location.jsonPointer + '/' + key, | ||
isValidated: location.isValidated | ||
class Location { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The URL class has many convenient methods to calculate if the URL is absolute and relative and compose it.
Looking at this Location
class, I have afraid that we are going to replicate the URL
class in future.
So I wanted to point it out to reduce the burden you could face by developing it
3297481
to
034d32e
Compare
@Eomm I can't replace the hole Location class with an URL, we've got some custom logic here. I can use URL instead of split/join for schemaId and jsonPointer, but I'm not sure that it's a good idea. All the operations we have are quite simple and the URL is very slow in comparison. |
index.js
Outdated
|
||
this.isMerged = false | ||
this.mergedSchemaId = null | ||
this.mergedJsonPointer = null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is currently hard to follow why does it fix the issue and how it is fixed.
Would you mind to add some comment of step flow why it works? and how the usage of mergedJsonPointer
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@climba03003 @Eomm I will explain with an example. Sorry, it is not simple because the problem is not simple.
{
$id: 'root',
type: 'object',
properties: {
property1: { type: 'string' },
property2: {
type: 'object',
allOf: [
{
properties: {
property21: { $ref: '#/properties/property1' }
}
},
{
properties: {
property22: {
anyOf: [
{ type: 'string' },
{ type: 'number' }
]
}
}
}
]
}
}
}
-
When we meet property
allOf
, we create a merged schema and create a new unique id for it.
Line 458 in e6b3c5f
mergedSchema.$id = `merged_${randomUUID()}`
If we meet anyOf/oneOf/if inside the merged schema, we create a reference using the merged schema id.
property22
will have the next reference:merged_12...223#/properties/property22
. To create this reference, we should know the merged schema id. -
If somewhere inside the
allOf
schemas we meet a local reference like'#/properties/property1'
we have to resolve it. To do this, we should know the original schema reference, which isroot
in this case.
So that is why we need to keep two schemas ids when we build a serializer inside the allOf
property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Location
class now has two methods for getting schema id.
getSchemaId
- you should use it when you want to CREATE a new reference to some place in the schema. For example, for validation.getOriginSchemaId
- you should use it when you want to RESOLVE a reference that already exists.
I added corresponding comments in the code.
index.js
Outdated
addMergedSchema (schemaId, jsonPointer = '#') { | ||
this.isMerged = true | ||
this.mergedSchemaId = schemaId | ||
this.mergedJsonPointer = jsonPointer | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move this class into its own file under lib?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
@Eomm @climba03003 @Uzlopak PTAL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Thanks for the explanation, it's now more clear to me.
Thanks. I will test asap :) |
Fix #540