From d973bd95bb50c1012e2ce39c6e1f18be26a6b414 Mon Sep 17 00:00:00 2001 From: delvedor Date: Mon, 22 Aug 2016 12:25:32 +0200 Subject: [PATCH 1/3] Support for missing parameters --- index.js | 46 +++++++++++++++++++++++++--------------------- test.js | 26 +++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/index.js b/index.js index 3df51134..040f9e3f 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) => { + /* code += ` + if (obj.hasOwnProperty('${key}')) { + json += '${$asString(key)}:'`*/ code += ` - json += '${$asString(key)}:' - ` + if (obj.${key} !== undefined) { + json += '${$asString(key)}:'` const result = nested(laterCode, name, '.' + key, schema.properties[key]) @@ -150,7 +153,20 @@ 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!') + } + ` + } else { + code += ` + } + ` } }) @@ -202,48 +218,36 @@ 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': code += ` - json += $asNull() - ` + json += $asNull()` break case 'string': code += ` - json += $asString(obj${key}) - ` + json += $asString(obj${key})` break case 'number': case 'integer': code += ` - json += $asNumber(obj${key}) - ` + json += $asNumber(obj${key})` break case 'boolean': code += ` - json += $asBoolean(obj${key}) - ` + json += $asBoolean(obj${key})` break case 'object': funcName = (name + key).replace(/[-.\[\]]/g, '') laterCode = buildObject(schema, laterCode, funcName) code += ` - json += ${funcName}(obj${key}) - ` + json += ${funcName}(obj${key})` break case 'array': funcName = (name + key).replace(/[-.\[\]]/g, '') laterCode = buildArray(schema, laterCode, funcName) code += ` - json += ${funcName}(obj${key}) - ` + json += ${funcName}(obj${key})` break default: throw new Error(`${type} unsupported`) 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' })) +}) From 970d177e3dca7e3c0364e6b6a3231d83aea6e6a3 Mon Sep 17 00:00:00 2001 From: delvedor Date: Mon, 22 Aug 2016 14:36:40 +0200 Subject: [PATCH 2/3] Fixed code and added comments --- index.js | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/index.js b/index.js index 040f9e3f..bc92ca87 100644 --- a/index.js +++ b/index.js @@ -140,12 +140,12 @@ function buildObject (schema, code, name) { var laterCode = '' Object.keys(schema.properties).forEach((key, i, a) => { - /* code += ` - if (obj.hasOwnProperty('${key}')) { - json += '${$asString(key)}:'`*/ + // 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 += ` if (obj.${key} !== undefined) { - json += '${$asString(key)}:'` + json += '${$asString(key)}:' + ` const result = nested(laterCode, name, '.' + key, schema.properties[key]) @@ -154,20 +154,20 @@ function buildObject (schema, code, name) { if (i < a.length - 1) { code += ` - json += \',\'` + json += \',\' + ` } if (schema.properties[key].required) { code += ` } else { throw new Error('${key} is required!') - } - ` - } else { - code += ` - } ` } + + code += ` + } + ` }) code += ` @@ -222,32 +222,38 @@ function nested (laterCode, name, key, schema) { switch (type) { case 'null': code += ` - json += $asNull()` + json += $asNull() + ` break case 'string': code += ` - json += $asString(obj${key})` + json += $asString(obj${key}) + ` break case 'number': case 'integer': code += ` - json += $asNumber(obj${key})` + json += $asNumber(obj${key}) + ` break case 'boolean': code += ` - json += $asBoolean(obj${key})` + json += $asBoolean(obj${key}) + ` break case 'object': funcName = (name + key).replace(/[-.\[\]]/g, '') laterCode = buildObject(schema, laterCode, funcName) code += ` - json += ${funcName}(obj${key})` + json += ${funcName}(obj${key}) + ` break case 'array': funcName = (name + key).replace(/[-.\[\]]/g, '') laterCode = buildArray(schema, laterCode, funcName) code += ` - json += ${funcName}(obj${key})` + json += ${funcName}(obj${key}) + ` break default: throw new Error(`${type} unsupported`) From 09624d511fcd23c4d4b8d3868f08a6fd4a87167c Mon Sep 17 00:00:00 2001 From: delvedor Date: Mon, 22 Aug 2016 14:36:55 +0200 Subject: [PATCH 3/3] Updated docs --- README.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) 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).