{"action":"created","issue":{"url":"https://api.github.com/repos/jurassix/joi-validation-strategy/issues/5","labels_url":"https://api.github.com/repos/jurassix/joi-validation-strategy/issues/5/labels{/name}","comments_url":"https://api.github.com/repos/jurassix/joi-validation-strategy/issues/5/comments","events_url":"https://api.github.com/repos/jurassix/joi-validation-strategy/issues/5/events","html_url":"https://github.com/jurassix/joi-validation-strategy/issues/5","id":116865010,"number":5,"title":"Breaks with Joi schema that has nested objects","user":{"login":"natorojr","id":1237186,"avatar_url":"https://avatars.githubusercontent.com/u/1237186?v=3","gravatar_id":"","url":"https://api.github.com/users/natorojr","html_url":"https://github.com/natorojr","followers_url":"https://api.github.com/users/natorojr/followers","following_url":"https://api.github.com/users/natorojr/following{/other_user}","gists_url":"https://api.github.com/users/natorojr/gists{/gist_id}","starred_url":"https://api.github.com/users/natorojr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/natorojr/subscriptions","organizations_url":"https://api.github.com/users/natorojr/orgs","repos_url":"https://api.github.com/users/natorojr/repos","events_url":"https://api.github.com/users/natorojr/events{/privacy}","received_events_url":"https://api.github.com/users/natorojr/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":6,"created_at":"2015-11-13T22:21:58Z","updated_at":"2015-11-20T21:38:53Z","closed_at":null,"body":"I have configured the following Joi validation schemas as my validatorTypes:\r\n\r\n```js\r\n  validatorTypes() {\r\n    return Joi.object({\r\n      form: Joi.object({\r\n        username: Joi.string().alphanum().min(3).max(30).label('Username'),\r\n        email: Joi.string().email().label('Email address'),\r\n        password: Joi.string().min(6).max(30).label('Password')\r\n      })\r\n      .or('form.username', 'form.email')\r\n      .label('Your form')\r\n    });\r\n  }\r\n```\r\n\r\nWhen I submit my form completely blank and run validate, I get the following as `this.props.errors` in my component:\r\n\r\n```json\r\n{\r\n  \"form\": [\r\n    \"\\\"Your form\\\" must contain at least one of [form.username, form.email]\"\r\n  ]\r\n}\r\n```\r\n\r\nAs you can see, it's obviously missing the other validation errors for username, password, and email.\r\n\r\nI debugged your code and discovered that Joi itself is returning the correct errors structure, as follows:\r\n\r\n```json\r\n{\r\n    \"name\": \"ValidationError\",\r\n    \"details\": [\r\n        {\r\n            \"message\": \"\\\"Username\\\" is not allowed to be empty\",\r\n            \"path\": \"form.username\",\r\n            \"type\": \"any.empty\",\r\n            \"context\": {\r\n                \"key\": \"Username\"\r\n            }\r\n        },\r\n        {\r\n            \"message\": \"\\\"Username\\\" must only contain alpha-numeric characters\",\r\n            \"path\": \"form.username\",\r\n            \"type\": \"string.alphanum\",\r\n            \"context\": {\r\n                \"value\": \"\",\r\n                \"key\": \"Username\"\r\n            }\r\n        },\r\n        {\r\n            \"message\": \"\\\"Username\\\" length must be at least 3 characters long\",\r\n            \"path\": \"form.username\",\r\n            \"type\": \"string.min\",\r\n            \"context\": {\r\n                \"limit\": 3,\r\n                \"value\": \"\",\r\n                \"key\": \"Username\"\r\n            }\r\n        },\r\n        {\r\n            \"message\": \"\\\"Email address\\\" is not allowed to be empty\",\r\n            \"path\": \"form.email\",\r\n            \"type\": \"any.empty\",\r\n            \"context\": {\r\n                \"key\": \"Email address\"\r\n            }\r\n        },\r\n        {\r\n            \"message\": \"\\\"Email address\\\" must be a valid email\",\r\n            \"path\": \"form.email\",\r\n            \"type\": \"string.email\",\r\n            \"context\": {\r\n                \"value\": \"\",\r\n                \"key\": \"Email address\"\r\n            }\r\n        },\r\n        {\r\n            \"message\": \"\\\"Password\\\" is not allowed to be empty\",\r\n            \"path\": \"form.password\",\r\n            \"type\": \"any.empty\",\r\n            \"context\": {\r\n                \"key\": \"Password\"\r\n            }\r\n        },\r\n        {\r\n            \"message\": \"\\\"Password\\\" length must be at least 6 characters long\",\r\n            \"path\": \"form.password\",\r\n            \"type\": \"string.min\",\r\n            \"context\": {\r\n                \"limit\": 6,\r\n                \"value\": \"\",\r\n                \"key\": \"Password\"\r\n            }\r\n        },\r\n        {\r\n            \"message\": \"\\\"Your form\\\" must contain at least one of [form.username, form.email]\",\r\n            \"path\": \"form\",\r\n            \"type\": \"object.missing\",\r\n            \"context\": {\r\n                \"peers\": [\r\n                    \"form.username\",\r\n                    \"form.email\"\r\n                ],\r\n                \"key\": \"Your form\"\r\n            }\r\n        }\r\n    ],\r\n    \"_object\": {\r\n        \"form\": {\r\n            \"role\": \"\",\r\n            \"somefield\": \"\",\r\n            \"username\": \"\",\r\n            \"email\": \"\",\r\n            \"password\": \"\"\r\n        }\r\n    }\r\n}\r\n```\r\n\r\nYour code `_collectErrors` [here](https://github.com/jurassix/joi-validation-strategy/blob/master/src/joiValidationStrategy.js#L19), which parses the Joi error structure, also correctly returns:\r\n\r\n```json\r\n{\r\n    \"form.username\": [\r\n        \"\\\"Username\\\" is not allowed to be empty\",\r\n        \"\\\"Username\\\" must only contain alpha-numeric characters\",\r\n        \"\\\"Username\\\" length must be at least 3 characters long\"\r\n    ],\r\n    \"form.email\": [\r\n        \"\\\"Email address\\\" is not allowed to be empty\",\r\n        \"\\\"Email address\\\" must be a valid email\"\r\n    ],\r\n    \"form.password\": [\r\n        \"\\\"Password\\\" is not allowed to be empty\",\r\n        \"\\\"Password\\\" length must be at least 6 characters long\"\r\n    ],\r\n    \"form\": [\r\n        \"\\\"Your form\\\" must contain at least one of [form.username, form.email]\"\r\n    ]\r\n}\r\n```\r\n\r\nHowever, after passing through your `hydrate` utility [here](https://github.com/jurassix/joi-validation-strategy/blob/master/src/joiValidationStrategy.js#L21), the nested results (e.g., 'form.username', 'form.password', 'form.email') are clobbered by the final call to `lodash.set` with path of 'form', resulting in:\r\n\r\n```json\r\n{\r\n  \"form\": [\r\n    \"\\\"Your form\\\" must contain at least one of [form.username, form.email]\"\r\n  ]\r\n}\r\n```\r\n\r\nMy immediate thought upon discovering this problem was \"why bother hydrating\"? When you validate and/or get validation messages you're actually referring to the the fields as key paths of the form 'form.username', 'form.password', etc.  I don't see the value in needing to access nested errors like this: `this.props.errors.form.password` when you can either do `this.props.errors['form.password']` or this.props.getValidationMessages('form.password').\r\n\r\nWould love to hear your thoughts on a possible workaround or solution.\r\n\r\nThanks in advance.\r\n"},"comment":{"url":"https://api.github.com/repos/jurassix/joi-validation-strategy/issues/comments/158531590","html_url":"https://github.com/jurassix/joi-validation-strategy/issues/5#issuecomment-158531590","issue_url":"https://api.github.com/repos/jurassix/joi-validation-strategy/issues/5","id":158531590,"user":{"login":"jurassix","id":1869117,"avatar_url":"https://avatars.githubusercontent.com/u/1869117?v=3","gravatar_id":"","url":"https://api.github.com/users/jurassix","html_url":"https://github.com/jurassix","followers_url":"https://api.github.com/users/jurassix/followers","following_url":"https://api.github.com/users/jurassix/following{/other_user}","gists_url":"https://api.github.com/users/jurassix/gists{/gist_id}","starred_url":"https://api.github.com/users/jurassix/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jurassix/subscriptions","organizations_url":"https://api.github.com/users/jurassix/orgs","repos_url":"https://api.github.com/users/jurassix/repos","events_url":"https://api.github.com/users/jurassix/events{/privacy}","received_events_url":"https://api.github.com/users/jurassix/received_events","type":"User","site_admin":false},"created_at":"2015-11-20T21:38:53Z","updated_at":"2015-11-20T21:38:53Z","body":"@natorojr @danlopez191 Thanks for more info. \r\n\r\nJoi flattens validation results. When I collect and then rebuild the errors object things start breaking down; order from Joi and Lodash.set can clobber data. \r\n\r\n@natorojr issue is specifically the order we rebuild the object. The last value `form` wipes out the previous values:\r\n\r\n```js\r\n{\r\n    \"form.username\": [\r\n        \"\\\"Username\\\" is not allowed to be empty\",\r\n        \"\\\"Username\\\" must only contain alpha-numeric characters\",\r\n        \"\\\"Username\\\" length must be at least 3 characters long\"\r\n    ],\r\n    \"form.email\": [\r\n        \"\\\"Email address\\\" is not allowed to be empty\",\r\n        \"\\\"Email address\\\" must be a valid email\"\r\n    ],\r\n    \"form.password\": [\r\n        \"\\\"Password\\\" is not allowed to be empty\",\r\n        \"\\\"Password\\\" length must be at least 6 characters long\"\r\n    ],\r\n    \"form\": [\r\n        \"\\\"Your form\\\" must contain at least one of [form.username, form.email]\"\r\n    ]\r\n}\r\n```\r\n\r\n@danlopez191 issue is that Joi is not zero indexed and so `\"emailInvites.1\": \"value\"` translates to [null, ,\"value\"]`\r\n\r\nLeaving the validations flat was problematic in previous issues:\r\n[#42](https://github.com/jurassix/react-validation-mixin/issues/42)\r\n[#39](https://github.com/jurassix/react-validation-mixin/issues/39)\r\n[#38](https://github.com/jurassix/react-validation-mixin/issues/38)\r\n\r\nThe complexity is pretty high here. I think we need to be able to hydrate the resulting Joi errors into a object that matches the original schema; that is what `hydrate` is try into achieve. Maybe we need to look at Joi for existing utils that can do this for us; a util that takes a _schema_ and the _errors_ and assembles them."}}