diff --git a/lib/errors.js b/lib/errors.js index 001b31f9e..4676059bc 100644 --- a/lib/errors.js +++ b/lib/errors.js @@ -252,7 +252,7 @@ internals.annotate = function (stripColorCodes) { let ref = obj; for (let j = 0; j < path.length && ref; ++j) { const seg = path[j]; - if (j + 1 < path.length) { + if (j + 1 < path.length && typeof ref[seg] !== 'string') { ref = ref[seg]; } else { @@ -279,10 +279,12 @@ internals.annotate = function (stripColorCodes) { } else if (lookup[error.path]) { const replacement = lookup[error.path]; - const appended = replacement.replace('_$end$_', `, ${pos}_$end$_`); - ref[appended] = ref[replacement]; - lookup[error.path] = appended; - delete ref[replacement]; + if (typeof ref[replacement] !== 'string') { + const appended = replacement.replace('_$end$_', `, ${pos}_$end$_`); + ref[appended] = ref[replacement]; + lookup[error.path] = appended; + delete ref[replacement]; + } } else { ref[`_$miss$_${seg}|${pos}_$end$_`] = '__missing__'; diff --git a/test/errors.js b/test/errors.js index 668513893..8e52a2228 100644 --- a/test/errors.js +++ b/test/errors.js @@ -609,5 +609,25 @@ describe('errors', () => { done(); }); }); + + it('pinpoints an error in a stringified JSON object', (done) => { + + const object = { + a: '{"c":"string"}' + }; + + const schema = { + a: Joi.object({ + b: Joi.string() + }) + }; + + Joi.validate(object, schema, { abortEarly: false }, (err, value) => { + + expect(err).to.exist(); + expect(err.annotate(true)).to.equal('{\n \"a\" [1]: \"{\\\"c\\\":\\\"string\\\"}\"\n}\n\n[1] \"c\" is not allowed'); + done(); + }); + }); }); }); diff --git a/test/index.js b/test/index.js index b87ce97a1..b4b1d79d0 100644 --- a/test/index.js +++ b/test/index.js @@ -1760,6 +1760,25 @@ describe('Joi', () => { }).to.throw('invalid value'); done(); }); + + it('throws a validation error and not a TypeError when parameter is given as a json string with incorrect property', (done) => { + + const schema = { + a: Joi.object({ + b: Joi.string() + }) + }; + + const input = { + a: '{"c":"string"}' + }; + + expect(() => { + + Joi.attempt(input, schema); + }).to.throw(/\"c\" is not allowed/); + done(); + }); }); describe('compile()', () => {