swagger-api / swagger-api/swagger-codegen
[JAVASCRIPT] Cannot handle circular schema dependencies
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
If you have a schema that references itself the generate code has a bug when running in the browser (i.e. not for node) where the model is referenced before it is defined. So if you call Model.constructFromObject(...) you receive the error:
Cannot read property 'constructFromObject' of undefined
Swagger-codegen version
2.3.1
Swagger declaration file content or url
swagger: "2.0"
info:
title: Sample API
version: 1.0.0
definitions:
Person:
properties:
name:
type: string
parent:
$ref: '#/definitions/Person'
paths:
/person:
get:
produces:
- application/json
responses:
200:
schema:
$ref: '#/definitions/Person'
Command line used for generation
swagger-codegen generate -o ./client -l javascript -i ./api.yaml
Steps to reproduce
- Generate client code using the above yaml file
- Add index.html to
src/dir:
<html>
<script src="./model/Person.js"></script>
<script>
window.SampleApi.Person.constructFromObject({ parent: { name : "hat" } })
</script>
</html>
- Browse to this page
- See error in console:
Person.js:70 Uncaught TypeError: Cannot read property 'constructFromObject' of undefined
at Function.exports.constructFromObject (Person.js:70)
at (index):4
Related issues/PRs
I think this is a duplicate of #6879 but that is not entirely clear from the issue description
Suggest a fix/enhancement
src/models/Person.js looks like this:
root.SampleApi.Person = factory(root.SampleApi.ApiClient, root.SampleApi.Person);
}
}(this, function(ApiClient, Person) {
...
exports.constructFromObject = function(data, obj) {
if (data) {
obj = obj || new exports();
if (data.hasOwnProperty('name')) {
obj['name'] = ApiClient.convertToType(data['name'], 'String');
}
if (data.hasOwnProperty('parent')) {
// ** Person is undefined here **
obj['parent'] = Person.constructFromObject(data['parent']);
}
}
return obj;
}
...
So root.SampleApi.Person is passed in as input to its own factory function, it is undefined at this time obviously.
Potential fix:
Pass in a reference to the API object to the factory rather than the specific models:
// root.SampleApi.Person = factory(root.SampleApi.ApiClient, root.SampleApi.Person);
root.SampleApi.Person = factory(root.SampleApi); // added
}
// }(this, function(ApiClient, Person) {
}(this, function(SampleApi) { // added
...
exports.constructFromObject = function(data, obj) {
var ApiClient = SampleApi.ApiClient // added
var Person = SampleApi.Person // added
...
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue with the supplied Swagger YAML and the swagger-codegen generate -l javascript command, then inspect the generated src/models/Person.js factory and compare issue #6879. Trace how circular model references are initialized in the browser, and verify that Person.constructFromObject handles the self-reference without an undefined-model error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100