diff --git a/README.md b/README.md
index d8d9beb0..b454cb70 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,7 @@ fast-json-stringify-uglified obj x 5,331,581 ops/sec ±0.73% (91 runs sampled)
- `Reuse - $ref`
- `Long integers`
- `Uglify`
+ - `Nullable`
- `Acknowledgements`
- `License`
@@ -462,6 +463,35 @@ const stringify = fastJson({
console.log(stringify({ some: 'object' })) // '{"some":"object"}'
```
+
+#### Nullable
+
+According to the [Open API 3.0 specification](https://swagger.io/docs/specification/data-models/data-types/#null), a value that can be null must be declared `nullable`.
+
+##### Nullable object
+```javascript
+const stringify = fastJson({
+ 'title': 'Nullable schema',
+ 'type': 'object',
+ 'nullable': true,
+ 'properties': {
+ 'product': {
+ 'nullable': true,
+ 'type': 'object',
+ 'properties': {
+ 'name': {
+ 'type': 'string'
+ }
+ }
+ }
+ }
+})
+
+console.log(stringify({product: {name: "hello"}})) // "{"product":{"name":"hello"}}"
+console.log(stringify({product: null})) // "{"product":null}"
+console.log(stringify(null)) // null
+```
+
## Acknowledgements
diff --git a/index.js b/index.js
index dca5cd47..d56665a1 100644
--- a/index.js
+++ b/index.js
@@ -621,6 +621,15 @@ function toJSON (variableName) {
function buildObject (schema, code, name, externalSchema, fullSchema) {
code += `
function ${name} (input) {
+ `
+ if (schema.nullable) {
+ code += `
+ if(input === null) {
+ return '${$asNull()}';
+ }
+ `
+ }
+ code += `
var obj = ${toJSON('input')}
var json = '{'
var addComma = false
diff --git a/test/toJSON.test.js b/test/toJSON.test.js
index 25fd23d4..04ac2975 100644
--- a/test/toJSON.test.js
+++ b/test/toJSON.test.js
@@ -81,3 +81,94 @@ test('not use toJSON if does not exist', (t) => {
t.equal('{"product":{"name":"cola"}}', stringify(object))
})
+
+test('not fail on null object declared nullable', (t) => {
+ t.plan(1)
+
+ const stringify = build({
+ title: 'simple object',
+ type: 'object',
+ nullable: true,
+ properties: {
+ product: {
+ type: 'object',
+ properties: {
+ name: {
+ type: 'string'
+ }
+ }
+ }
+ }
+ })
+ t.equal('null', stringify(null))
+})
+
+test('not fail on null sub-object declared nullable', (t) => {
+ t.plan(1)
+
+ const stringify = build({
+ title: 'simple object',
+ type: 'object',
+ properties: {
+ product: {
+ nullable: true,
+ type: 'object',
+ properties: {
+ name: {
+ type: 'string'
+ }
+ }
+ }
+ }
+ })
+ const object = {
+ product: null
+ }
+ t.equal('{"product":null}', stringify(object))
+})
+
+test('throw an error on non nullable null sub-object', (t) => {
+ t.plan(1)
+
+ const stringify = build({
+ title: 'simple object',
+ type: 'object',
+ properties: {
+ product: {
+ nullable: false,
+ type: 'object',
+ properties: {
+ name: {
+ type: 'string'
+ }
+ }
+ }
+ }
+ })
+ const object = {
+ product: null
+ }
+ t.throws(() => { stringify(object) })
+})
+
+test('throw an error on non nullable null object', (t) => {
+ t.plan(1)
+
+ const stringify = build({
+ title: 'simple object',
+ nullable: false,
+ type: 'object',
+ properties: {
+ product: {
+ nullable: false,
+ type: 'object',
+ properties: {
+ name: {
+ type: 'string'
+ }
+ }
+ }
+ }
+ })
+ t.throws(() => { stringify(null) })
+})