diff --git a/README.md b/README.md index 822bcf1c..af6c683a 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ And nested ones, too. | `Date` | `string` via `toISOString()` | | `RegExp` | `string` | -#### Required +#### Required You can set specific fields of an object as `required` in your schema, by adding `required: true` inside the key properties. Example: ```javascript @@ -94,6 +94,31 @@ const schema = { ``` If the object to stringify has not the required field(s), `fast-json-stringify` will throw an error. +#### Missing fields +If a field *is present* in the schema (and is not required) but it *is not present* in the object to stringify, `fast-json-stringify` will not write it in the final string. +Example: +```javascript +const stringify = fastJson({ + title: 'Example Schema', + type: 'object', + properties: { + nickname: { + type: 'string' + }, + mail: { + type: 'string', + required: true + } + } +}) + +const obj = { + mail: 'mail@example.com' +} + +console.log(stringify(obj)) // '{"mail":"mail@example.com"}' +``` + ## Acknowledgements This project was kindly sponsored by [nearForm](http://nearform.com). diff --git a/index.js b/index.js index 3df51134..bc92ca87 100644 --- a/index.js +++ b/index.js @@ -140,9 +140,12 @@ function buildObject (schema, code, name) { var laterCode = '' Object.keys(schema.properties).forEach((key, i, a) => { + // Using obj.key !== undefined instead of obj.hasOwnProperty(prop) for perf reasons, + // see https://github.com/mcollina/fast-json-stringify/pull/3 for discussion. code += ` - json += '${$asString(key)}:' - ` + if (obj.${key} !== undefined) { + json += '${$asString(key)}:' + ` const result = nested(laterCode, name, '.' + key, schema.properties[key]) @@ -150,8 +153,21 @@ function buildObject (schema, code, name) { laterCode = result.laterCode if (i < a.length - 1) { - code += 'json += \',\'' + code += ` + json += \',\' + ` + } + + if (schema.properties[key].required) { + code += ` + } else { + throw new Error('${key} is required!') + ` } + + code += ` + } + ` }) code += ` @@ -202,12 +218,6 @@ function buildArray (schema, code, name) { function nested (laterCode, name, key, schema) { var code = '' var funcName - if (schema.required) { - code += ` - if (!obj.hasOwnProperty('${key.slice(1)}')) { - throw new Error('${key} is required!') - }` - } const type = schema.type switch (type) { case 'null': diff --git a/test.js b/test.js index a69d5ee5..69edd878 100644 --- a/test.js +++ b/test.js @@ -288,7 +288,31 @@ test('object with required field', (t) => { }) t.fail() } catch (e) { - t.is(e.message, '.str is required!') + t.is(e.message, 'str is required!') t.pass() } }) + +test('missing values', (t) => { + t.plan(3) + + const stringify = build({ + title: 'object with missing values', + type: 'object', + properties: { + str: { + type: 'string' + }, + num: { + type: 'number' + }, + val: { + type: 'string' + } + } + }) + + t.equal('{"val":"value"}', stringify({ val: 'value' })) + t.equal('{"str":"string","val":"value"}', stringify({ str: 'string', val: 'value' })) + t.equal('{"str":"string","num":42,"val":"value"}', stringify({ str: 'string', num: 42, val: 'value' })) +})