mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-13 04:16:34 +03:00
Handle circular references
This commit is contained in:
parent
e5a5e692eb
commit
afb9f6b1ed
|
@ -43,7 +43,9 @@ export default class JsonSchema extends BaseComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.joinAllOf(schema, {omitParent: true});
|
this.joinAllOf(schema, {omitParent: true});
|
||||||
|
if (!schema.type) {
|
||||||
|
schema.type = 'object';
|
||||||
|
}
|
||||||
if (schema.type !== 'object') {
|
if (schema.type !== 'object') {
|
||||||
this.isTrivial = true;
|
this.isTrivial = true;
|
||||||
this._displayType = schema.type;
|
this._displayType = schema.type;
|
||||||
|
@ -101,7 +103,7 @@ export default class JsonSchema extends BaseComponent {
|
||||||
if (propData.type === 'array') {
|
if (propData.type === 'array') {
|
||||||
let itemType = propData.items.type;
|
let itemType = propData.items.type;
|
||||||
let itemFormat = propData.items.format;
|
let itemFormat = propData.items.format;
|
||||||
if (itemType === 'object') {
|
if (itemType === 'object' || !itemType) {
|
||||||
itemType = propData.items.title || 'object';
|
itemType = propData.items.title || 'object';
|
||||||
propData._pointer = propData.items._pointer || JsonPointer.join(this.pointer, ['properties', prop, 'items']);
|
propData._pointer = propData.items._pointer || JsonPointer.join(this.pointer, ['properties', prop, 'items']);
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,27 +99,39 @@ export class BaseComponent {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* simple in-place schema dereferencing. Schema is already bundled so no need in global dereferencing.
|
* simple in-place schema dereferencing. Schema is already bundled so no need in global dereferencing.
|
||||||
* TODO: doesn't support circular references
|
|
||||||
*/
|
*/
|
||||||
dereference(schema = Object.assign({}, this.componentSchema)) {
|
dereference(schema = Object.assign({}, this.componentSchema)) {
|
||||||
//schema = Object.assign({}, schema);
|
let dereferencedCache = {};
|
||||||
if (schema && schema.$ref) {
|
|
||||||
let resolved = this.schemaMgr.byPointer(schema.$ref);
|
|
||||||
let baseName = JsonPointer.baseName(schema.$ref);
|
|
||||||
// if resolved schema doesn't have title use name from ref
|
|
||||||
resolved = Object.assign({}, resolved);
|
|
||||||
resolved.title = resolved.title || baseName;
|
|
||||||
resolved._pointer = schema.$ref;
|
|
||||||
Object.assign(schema, resolved);
|
|
||||||
delete schema.$ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(schema).forEach((key) => {
|
let resolve = (schema) => {
|
||||||
let value = schema[key];
|
if (schema && schema.$ref) {
|
||||||
if (value && typeof value === 'object') {
|
let resolved = this.schemaMgr.byPointer(schema.$ref);
|
||||||
this.dereference(value);
|
let baseName = JsonPointer.baseName(schema.$ref);
|
||||||
|
if (!dereferencedCache[schema.$ref]) {
|
||||||
|
// if resolved schema doesn't have title use name from ref
|
||||||
|
resolved = Object.assign({}, resolved);
|
||||||
|
resolved._pointer = schema.$ref;
|
||||||
|
} else {
|
||||||
|
// for circular referenced save only title and type
|
||||||
|
resolved = {
|
||||||
|
title: resolved.title
|
||||||
|
};
|
||||||
|
}
|
||||||
|
resolved.title = resolved.title || baseName;
|
||||||
|
Object.assign(schema, resolved);
|
||||||
|
dereferencedCache[schema.$ref] = true;
|
||||||
|
delete schema.$ref;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
Object.keys(schema).forEach((key) => {
|
||||||
|
let value = schema[key];
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
resolve(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
resolve(schema);
|
||||||
this.componentSchema = schema;
|
this.componentSchema = schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,25 @@ describe('Redoc components', () => {
|
||||||
paramWithRef.items.schema.type.should.be.equal('object');
|
paramWithRef.items.schema.type.should.be.equal('object');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('circular dereference', () => {
|
||||||
|
let paramWithRef;
|
||||||
|
beforeAll(() => {
|
||||||
|
component.pointer = '/paths/test4/get';
|
||||||
|
component.ngOnInit();
|
||||||
|
component.dereference();
|
||||||
|
paramWithRef = component.componentSchema.parameters[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should resolve circular schema', () => {
|
||||||
|
expect(paramWithRef.$ref).toBeUndefined();
|
||||||
|
expect(paramWithRef.items.schema.$ref).toBeUndefined();
|
||||||
|
paramWithRef.type.should.be.equal('array');
|
||||||
|
paramWithRef._pointer.should.be.equal('#/definitions/Circular');
|
||||||
|
expect(paramWithRef.items.schema._pointer).toBeUndefined();
|
||||||
|
paramWithRef.items.schema.title.should.be.equal('Circular');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('mergeAllOf', () => {
|
describe('mergeAllOf', () => {
|
||||||
|
|
|
@ -31,6 +31,14 @@
|
||||||
"$ref": "#/definitions/Simple"
|
"$ref": "#/definitions/Simple"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Circular": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Circular"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"paths": {
|
"paths": {
|
||||||
|
@ -63,6 +71,16 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"test4": {
|
||||||
|
"get": {
|
||||||
|
"summary": "test get",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/Circular"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user