{"action":"created","issue":{"url":"https://api.github.com/repos/raml-org/raml-js-parser-2/issues/560","repository_url":"https://api.github.com/repos/raml-org/raml-js-parser-2","labels_url":"https://api.github.com/repos/raml-org/raml-js-parser-2/issues/560/labels{/name}","comments_url":"https://api.github.com/repos/raml-org/raml-js-parser-2/issues/560/comments","events_url":"https://api.github.com/repos/raml-org/raml-js-parser-2/issues/560/events","html_url":"https://github.com/raml-org/raml-js-parser-2/issues/560","id":192200635,"number":560,"title":"Parser `toJSON()` method sets `\"required\": true` on types","user":{"login":"jstoiko","id":9660342,"avatar_url":"https://avatars.githubusercontent.com/u/9660342?v=3","gravatar_id":"","url":"https://api.github.com/users/jstoiko","html_url":"https://github.com/jstoiko","followers_url":"https://api.github.com/users/jstoiko/followers","following_url":"https://api.github.com/users/jstoiko/following{/other_user}","gists_url":"https://api.github.com/users/jstoiko/gists{/gist_id}","starred_url":"https://api.github.com/users/jstoiko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jstoiko/subscriptions","organizations_url":"https://api.github.com/users/jstoiko/orgs","repos_url":"https://api.github.com/users/jstoiko/repos","events_url":"https://api.github.com/users/jstoiko/events{/privacy}","received_events_url":"https://api.github.com/users/jstoiko/received_events","type":"User","site_admin":false},"labels":[{"id":442835088,"url":"https://api.github.com/repos/raml-org/raml-js-parser-2/labels/waiting-for-response","name":"waiting-for-response","color":"aaaaaa","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":5,"created_at":"2016-11-29T06:40:00Z","updated_at":"2016-12-03T22:20:58Z","closed_at":null,"body":"given the RAML file below:\r\n```raml\r\n#%RAML 1.0\r\ntitle: Person API\r\n\r\ntypes:\r\n  Address:\r\n    type: object\r\n    properties:\r\n      street:\r\n        type: string\r\n  Person:\r\n    type: object\r\n    properties:\r\n      home_address:\r\n        type: Address\r\n      work_address:\r\n        type: Address\r\n        required: false\r\n\r\n/humans:\r\n  post:\r\n    body:\r\n      application/json:\r\n        type: Person\r\n\r\n```\r\n\r\nand the following snippet:\r\n```js\r\nrequire('raml-1-parser')\r\n    .loadRAML(file, { rejectOnErrors: true })\r\n    .then(function (ramlApi) {\r\n      var raml = ramlApi.expand(true).toJSON({\r\n        serializeMetadata: false\r\n      })\r\n      console.log(JSON.stringify(raml, null, 2))\r\n}\r\n```\r\n\r\n`raml` will output:\r\n```json\r\n{\r\n  \"types\": [\r\n    {\r\n      \"Address\": {\r\n        \"name\": \"Address\",\r\n        \"displayName\": \"Address\",\r\n        \"type\": [\r\n          \"object\"\r\n        ],\r\n        \"required\": true,\r\n        \"properties\": {\r\n          \"street\": {\r\n            \"name\": \"street\",\r\n            \"displayName\": \"street\",\r\n            \"type\": [\r\n              \"string\"\r\n            ],\r\n            \"required\": true\r\n          }\r\n        }\r\n      }\r\n    },\r\n    {\r\n      \"Person\": {\r\n        \"name\": \"Person\",\r\n        \"displayName\": \"Person\",\r\n        \"type\": [\r\n          \"object\"\r\n        ],\r\n        \"required\": true,\r\n        \"properties\": {\r\n          \"home_address\": {\r\n            \"name\": \"home_address\",\r\n            \"displayName\": \"home_address\",\r\n            \"type\": [\r\n              \"Address\"\r\n            ],\r\n            \"required\": true\r\n          },\r\n          \"work_address\": {\r\n            \"name\": \"work_address\",\r\n            \"displayName\": \"work_address\",\r\n            \"type\": [\r\n              \"Address\"\r\n            ],\r\n            \"required\": false\r\n          }\r\n        }\r\n      }\r\n    }\r\n  ],\r\n  \"title\": \"Person API\",\r\n  \"resources\": [\r\n    {\r\n      \"methods\": [\r\n        {\r\n          \"body\": {\r\n            \"application/json\": {\r\n              \"name\": \"application/json\",\r\n              \"displayName\": \"application/json\",\r\n              \"type\": [\r\n                \"Person\"\r\n              ],\r\n              \"required\": true\r\n            }\r\n          },\r\n          \"method\": \"post\"\r\n        }\r\n      ],\r\n      \"relativeUri\": \"/humans\",\r\n      \"displayName\": \"/humans\",\r\n      \"relativeUriPathSegments\": [\r\n        \"humans\"\r\n      ]\r\n    }\r\n  ]\r\n}\r\n```\r\n\r\nThe issue is that the type `Address` has had `\"required\": true` set by the parser and as a result, any properties that would try to inherit from it, e.g. `Person.work_address` will not be able to (see [this](https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#object-type-specialization))."},"comment":{"url":"https://api.github.com/repos/raml-org/raml-js-parser-2/issues/comments/264669479","html_url":"https://github.com/raml-org/raml-js-parser-2/issues/560#issuecomment-264669479","issue_url":"https://api.github.com/repos/raml-org/raml-js-parser-2/issues/560","id":264669479,"user":{"login":"ddenisenko","id":14824966,"avatar_url":"https://avatars.githubusercontent.com/u/14824966?v=3","gravatar_id":"","url":"https://api.github.com/users/ddenisenko","html_url":"https://github.com/ddenisenko","followers_url":"https://api.github.com/users/ddenisenko/followers","following_url":"https://api.github.com/users/ddenisenko/following{/other_user}","gists_url":"https://api.github.com/users/ddenisenko/gists{/gist_id}","starred_url":"https://api.github.com/users/ddenisenko/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ddenisenko/subscriptions","organizations_url":"https://api.github.com/users/ddenisenko/orgs","repos_url":"https://api.github.com/users/ddenisenko/repos","events_url":"https://api.github.com/users/ddenisenko/events{/privacy}","received_events_url":"https://api.github.com/users/ddenisenko/received_events","type":"User","site_admin":false},"created_at":"2016-12-03T22:20:58Z","updated_at":"2016-12-03T22:20:58Z","body":"I do not agree with this spec interpretation. `required: true` in question is set for the type `Address` itself, not for one of its properties. \r\n\r\nSpec in this paragraph regulates the changes of `required` for the properties in subclasses.\r\n\r\nExample:\r\n\r\nThis works:\r\n```\r\ntypes:\r\n  Address:\r\n    type: object\r\n    properties:\r\n      street:\r\n        type: string\r\n        required: true\r\n  Person:\r\n    type: object\r\n    properties:\r\n      home_address:\r\n        type: Address\r\n      work_address:\r\n        type: Address\r\n        properties:\r\n          street:\r\n            type: string\r\n            required: true\r\n```\r\n\r\nAnd this does not:\r\n\r\n```\r\ntypes:\r\n  Address:\r\n    type: object\r\n    properties:\r\n      street:\r\n        type: string\r\n        required: true\r\n  Person:\r\n    type: object\r\n    properties:\r\n      home_address:\r\n        type: Address\r\n      work_address:\r\n        type: Address\r\n        properties:\r\n          street:\r\n            type: string\r\n            required: false\r\n```\r\n\r\nNotice `required` changed to false in the `street` property of `work_address` property of `Person` type.\r\n\r\nI understand that this `required` in top-level type makes it more difficult for you to analyze types. We can consider removing it from top-level types. \r\n\r\nFor now you can use `__METADATA__` to find out where attribute is originating from, in other words you can determine whether an attribute does actually exist in RAML code, or is added by the parser.\r\n\r\nIn your example, JSON with metadata turned on is the following:\r\n```\r\n        \"Address\": {\r\n          \"name\": \"Address\",\r\n          \"displayName\": \"Address\",\r\n          \"type\": [\r\n            \"object\"\r\n          ],\r\n          \"required\": true,\r\n          \"properties\": {\r\n            \"street\": {\r\n              \"name\": \"street\",\r\n              \"displayName\": \"street\",\r\n              \"type\": [\r\n                \"string\"\r\n              ],\r\n              \"required\": true,\r\n              \"__METADATA__\": {\r\n                \"primitiveValuesMeta\": {\r\n                  \"displayName\": {\r\n                    \"calculated\": true\r\n                  }\r\n                }\r\n              }\r\n            }\r\n          },\r\n          \"__METADATA__\": {\r\n            \"primitiveValuesMeta\": {\r\n              \"displayName\": {\r\n                \"calculated\": true\r\n              },\r\n              \"required\": {\r\n                \"insertedAsDefault\": true\r\n              }\r\n            }\r\n          }\r\n        }\r\n      },\r\n```\r\n\r\nAs you can see, metadata of `Address` itself has \r\n```\r\n              \"required\": {\r\n                \"insertedAsDefault\": true\r\n              }\r\n```\r\nwhile same metadata of `street` does not. `insertedAsDefault` and `calculated` are two keywords  indicating there is no such attribute in the original code.\r\n\r\nTurning metadata info on sample:\r\n```\r\napi.toJSON({serializeMetadata: true})\r\n```"}}
{"actor":{"display_login":"ddenisenko"}}