diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 9d1a8c8ecee2867d357e86df24908a951af8fd91..35755d4b07cb6e8d34e7ba4573c90dc12dddbe0a 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -12,12 +12,12 @@ If you are submitting a bug report, please include the following:
 
 * When submitting *bug reports*, *paste your schema example* whenever possible. This will save us from having to ask you for it later.
 * When submitting *Pull Requests (PRs)*, you should request to merge your changes into our `develop` branch.
-* Our approach to testing is described in [spec/README.md](spec/README.md).
+* Our approach to testing is described in [spec/README.md](/spec/README.md).
 * PRs without specs will not be merged anytime soon!
 
 ## Releasing new versions
 
-* Create a new entry in the [CHANGELOG.md](CHANGELOG.md) file,
+* Create a new entry in the [CHANGELOG](/CHANGELOG) file,
 * Re-build and re-release the online demo, see [`website-jsf` gh-pages branch](https://github.com/json-schema-faker/website-jsf/tree/gh-pages).
 
 ## Development tasks
diff --git a/CHANGELOG b/CHANGELOG
index 23dd33776f026a747eb50e012ca92863eb988164..9706954f6672e44746fd19664674ebf09b55505b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+v0.5.0-rc15
+  date: 2018-04-07
+  changes:
+    - Introduced option: "optionalsProbability".
 v0.5.0-rc1
   date: 2017-04-10
   changes:
diff --git a/README.md b/README.md
index 44f26d8d21e317ea3a60c25a40a3ab2289bdcaa4..366674b851099a8ccbd8022f61e7b94417863f99 100644
--- a/README.md
+++ b/README.md
@@ -446,6 +446,7 @@ You may define following options for `jsf` that alter its behavior:
 - `maxLength`: number - Configure a maximum length to allow generating strings for. This will override the maximum length found inside a JSON Schema.
 - `random`: Function - a replacement for `Math.random` to support pseudorandom number generation.
 - `alwaysFakeOptionals`: boolean - When true, all object-properties will be generated regardless they're `required` or not.
+- `optionalsProbability`: number - A decimal number from 0 to 1 that indicates the probability to fake a non-required object property (default: 0). When `0.0`, only `required` properties will be generated; when `1.0`, all properties are generated. This option is overwritten to 1 when `alwaysFakeOptionals = true`.
 
 Set options just as below:
 
diff --git a/bower.json b/bower.json
index 47cd202e3b09ee5d73afc2c4278074cc6bf05cb8..930d8b254fa09edaa1b0075068005c6151175a06 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "json-schema-faker",
-  "version": "0.5.0-rc14",
+  "version": "0.5.0-rc15",
   "description": "JSON-Schema + fake data generators",
   "homepage": "http://json-schema-faker.js.org",
   "main": "dist/json-schema-faker.js",
diff --git a/dist/json-schema-faker.js b/dist/json-schema-faker.js
index 35a5a792b7bf0ef713e9cc106abb1dfa9b853471..4d3f593ed30afc6e933a703e43084f9cac93ef15 100644
Binary files a/dist/json-schema-faker.js and b/dist/json-schema-faker.js differ
diff --git a/dist/json-schema-faker.min.js b/dist/json-schema-faker.min.js
index 2452d1ebfbe774e113aae6a2d549cc8b2ba8902a..19b9d3cb6c81c770e3b857b29564f25ef4bfbd50 100644
Binary files a/dist/json-schema-faker.min.js and b/dist/json-schema-faker.min.js differ
diff --git a/lib/index.js b/lib/index.js
index 4f070437953d277ff6febf40a6f5a1046dd2cdd1..6625c0c1d83aea197cccc9236c50895ef2298cfe 100644
Binary files a/lib/index.js and b/lib/index.js differ
diff --git a/package-lock.json b/package-lock.json
index e1baef03129794efee79af31fb6c309b240af36d..88cab3940e0cbedb80d38baf7a2c167f50ba071a 100644
Binary files a/package-lock.json and b/package-lock.json differ
diff --git a/package.json b/package.json
index 5c3692bf3371574502c02792e96612f1c2e327b1..92097c6b43689c1e8281e8693ab7ea6935a2aca1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "json-schema-faker",
-  "version": "0.5.0-rc14",
+  "version": "0.5.0-rc15",
   "description": "JSON-Schema + fake data generators",
   "homepage": "http://json-schema-faker.js.org",
   "main": "lib/index.js",
diff --git a/spec/schema/core/option/alwaysFakeOptionals.js b/spec/schema/core/option/alwaysFakeOptionals.js
new file mode 100644
index 0000000000000000000000000000000000000000..035bd0f9879963ff2cd20bf7c79e527e50958e97
--- /dev/null
+++ b/spec/schema/core/option/alwaysFakeOptionals.js
@@ -0,0 +1,8 @@
+module.exports = {
+    register: function(jsf) {
+        return jsf.option({
+            'useDefaultValue': true,
+            'alwaysFakeOptionals': true
+        });
+    }
+};
diff --git a/spec/schema/core/option/alwaysFakeOptionals.json b/spec/schema/core/option/alwaysFakeOptionals.json
new file mode 100644
index 0000000000000000000000000000000000000000..609d6e3a1220bed337c5b32d5da648d7a898c208
--- /dev/null
+++ b/spec/schema/core/option/alwaysFakeOptionals.json
@@ -0,0 +1,44 @@
+[
+  {
+    "description": "alwaysFakeOptionals option",
+    "tests": [
+      {
+        "description": "should handle alwaysFakeOptionals option (= true) for objects",
+        "schema": {
+          "type": "object",
+          "properties": {
+            "optionalProperty1": { "type": "number", "default": 1 },
+            "optionalProperty2": { "type": "number", "default": 1 },
+            "optionalProperty3": { "type": "number", "default": 1 },
+            "optionalProperty4": { "type": "number", "default": 1 },
+            "optionalProperty5": { "type": "number", "default": 1 }
+          }
+        },
+        "valid": true,
+        "equal": {
+          "optionalProperty1": 1,
+          "optionalProperty2": 1,
+          "optionalProperty3": 1,
+          "optionalProperty4": 1,
+          "optionalProperty5": 1
+        },
+        "require": "core/option/alwaysFakeOptionals"
+      },
+      {
+        "description": "should handle alwaysFakeOptionals option (= true) for arrays",
+        "schema": {
+          "type": "array",
+          "items": {
+            "type": "string",
+            "enum": ["a"]
+          },
+          "maxItems": 5,
+          "minItems": 0
+        },
+        "valid": true,
+        "equal": ["a", "a", "a", "a", "a"],
+        "require": "core/option/alwaysFakeOptionals"
+      }
+    ]
+  }
+]
diff --git a/spec/schema/core/option/optionalsProbability.json b/spec/schema/core/option/optionalsProbability.json
new file mode 100644
index 0000000000000000000000000000000000000000..da53c1c970d6a797d603beb6eabfb8f892f0b2f2
--- /dev/null
+++ b/spec/schema/core/option/optionalsProbability.json
@@ -0,0 +1,96 @@
+[
+  {
+    "description": "optionalsProbability option",
+    "tests": [
+      {
+        "description": "should handle optionalsProbability option (default = 0) for objects",
+        "schema": {
+          "type": "object",
+          "properties": {
+            "optionalProperty1": { "type": "number", "default": 1 },
+            "optionalProperty2": { "type": "number", "default": 1 },
+            "optionalProperty3": { "type": "number", "default": 1 },
+            "optionalProperty4": { "type": "number", "default": 1 },
+            "optionalProperty5": { "type": "number", "default": 1 }
+          }
+        },
+        "valid": true,
+        "equal": {}
+      },
+      {
+        "description": "should handle optionalsProbability option (= 1) for objects",
+        "schema": {
+          "type": "object",
+          "properties": {
+            "optionalProperty1": { "type": "number", "default": 1 },
+            "optionalProperty2": { "type": "number", "default": 1 },
+            "optionalProperty3": { "type": "number", "default": 1 },
+            "optionalProperty4": { "type": "number", "default": 1 },
+            "optionalProperty5": { "type": "number", "default": 1 }
+          }
+        },
+        "valid": true,
+        "equal": {
+          "optionalProperty1": 1,
+          "optionalProperty2": 1,
+          "optionalProperty3": 1,
+          "optionalProperty4": 1,
+          "optionalProperty5": 1
+        },
+        "require": "core/option/optionalsProbabilityEquals1"
+      },
+      {
+        "description": "should handle optionalsProbability option (= 1) for arrays",
+        "schema": {
+          "type": "array",
+          "items": {
+            "type": "string",
+            "enum": ["a"]
+          },
+          "maxItems": 5,
+          "minItems": 0
+        },
+        "valid": true,
+        "equal": ["a", "a", "a", "a", "a"],
+        "require": "core/option/optionalsProbabilityEquals1"
+      },
+      {
+        "description": "should handle optionalsProbability option (= 0) overwritten by alwaysFakeOptionals for objects",
+        "schema": {
+          "type": "object",
+          "properties": {
+            "optionalProperty1": { "type": "number", "default": 1 },
+            "optionalProperty2": { "type": "number", "default": 1 },
+            "optionalProperty3": { "type": "number", "default": 1 },
+            "optionalProperty4": { "type": "number", "default": 1 },
+            "optionalProperty5": { "type": "number", "default": 1 }
+          }
+        },
+        "valid": true,
+        "equal": {
+          "optionalProperty1": 1,
+          "optionalProperty2": 1,
+          "optionalProperty3": 1,
+          "optionalProperty4": 1,
+          "optionalProperty5": 1
+        },
+        "require": "core/option/optionalsProbabilityOverwritten"
+      },
+      {
+        "description": "should handle optionalsProbability option (= 0) overwritten by alwaysFakeOptionals for objects",
+        "schema": {
+          "type": "array",
+          "items": {
+            "type": "string",
+            "enum": ["a"]
+          },
+          "maxItems": 5,
+          "minItems": 0
+        },
+        "valid": true,
+        "equal": ["a", "a", "a", "a", "a"],
+        "require": "core/option/optionalsProbabilityOverwritten"
+      }
+    ]
+  }
+]
diff --git a/spec/schema/core/option/optionalsProbabilityEquals1.js b/spec/schema/core/option/optionalsProbabilityEquals1.js
new file mode 100644
index 0000000000000000000000000000000000000000..c269a57e63ccfad948f098071ffb9ae2a3868d1a
--- /dev/null
+++ b/spec/schema/core/option/optionalsProbabilityEquals1.js
@@ -0,0 +1,8 @@
+module.exports = {
+    register: function(jsf) {
+        return jsf.option({
+            'useDefaultValue': true,
+            'optionalsProbability': 1.0
+        });
+    }
+};
diff --git a/spec/schema/core/option/optionalsProbabilityOverwritten.js b/spec/schema/core/option/optionalsProbabilityOverwritten.js
new file mode 100644
index 0000000000000000000000000000000000000000..d8aabc2010d2cad95fee694f40fe502b06f8af26
--- /dev/null
+++ b/spec/schema/core/option/optionalsProbabilityOverwritten.js
@@ -0,0 +1,9 @@
+module.exports = {
+    register: function(jsf) {
+        return jsf.option({
+            'useDefaultValue': true,
+            'alwaysFakeOptionals': true,
+            'optionalsProbability': 0.0
+        });
+    }
+};
diff --git a/spec/schema/core/option/random.json b/spec/schema/core/option/random.json
index f2bd48c35bf5e1e2118ed5576aebee0d01c0521a..2af07c2e4593660219b9b579b003f200bd8e632d 100644
--- a/spec/schema/core/option/random.json
+++ b/spec/schema/core/option/random.json
@@ -23,9 +23,9 @@
         },
         "valid": true,
         "equal": {
-          "a": 62,
-          "b": "amet voluptate qui reprehenderi",
-          "c": "fw538"
+          "a": 92,
+          "b": "enim veniam",
+          "c": "ff353"
         },
         "repeat": 1,
         "require": "core/option/random"
diff --git a/spec/schema/core/types/object.json b/spec/schema/core/types/object.json
index 1eeb036d4baffa70d08baf911d91635329a670e7..01ba47f89f991ac9c1f4774fe117a9b304241684 100644
--- a/spec/schema/core/types/object.json
+++ b/spec/schema/core/types/object.json
@@ -2,81 +2,81 @@
   {
     "description": "object generator",
     "tests": [
-        {
-          "description": "addP === false && !props && !patternProps",
-          "schema": {
-            "type": "object",
-            "additionalProperties": false
-          },
-          "valid": true
+      {
+        "description": "addP === false && !props && !patternProps",
+        "schema": {
+          "type": "object",
+          "additionalProperties": false
         },
-        {
-          "description": "addP === false && props && !patternProps",
-          "schema": {
-            "type": "object",
-            "properties": {
-                "count": {
-                    "type": "integer"
-                }
-            },
-            "additionalProperties": false
+        "valid": true
+      },
+      {
+        "description": "addP === false && props && !patternProps",
+        "schema": {
+          "type": "object",
+          "properties": {
+              "count": {
+                  "type": "integer"
+              }
           },
-          "valid": true
+          "additionalProperties": false
         },
-        {
-          "description": "addP === false && !props && patternProps",
-          "schema": {
-            "type": "object",
-            "patternProperties": {
-                "count": {
-                    "type": "integer"
-                }
-            },
-            "additionalProperties": false
+        "valid": true
+      },
+      {
+        "description": "addP === false && !props && patternProps",
+        "schema": {
+          "type": "object",
+          "patternProperties": {
+              "count": {
+                  "type": "integer"
+              }
           },
-          "valid": true
+          "additionalProperties": false
         },
-        {
-          "description": "addP === false && props && patternProps",
-          "schema": {
-            "type": "object",
-            "properties": {
-                "count": {
-                    "type": "integer"
-                }
-            },
-            "patternProperties": {
-                "v-[0-3]": {
-                    "type": "integer"
-                }
-            },
-            "additionalProperties": false
+        "valid": true
+      },
+      {
+        "description": "addP === false && props && patternProps",
+        "schema": {
+          "type": "object",
+          "properties": {
+              "count": {
+                  "type": "integer"
+              }
           },
-          "valid": true
-        },
-        {
-          "description": "addP === false && !props && !patternProps && minProperties",
-          "schema": {
-            "type": "object",
-            "minProperties": 2,
-            "additionalProperties": false
+          "patternProperties": {
+              "v-[0-3]": {
+                  "type": "integer"
+              }
           },
-          "throws": "missing properties for:\n[\\s\\S]+? in \\/"
+          "additionalProperties": false
         },
-        {
-          "description": "addP === undef || props",
-          "schema": {
-            "type": "object",
-            "minProperties": 2,
-            "properties": {
-                "count": {
-                    "type": "integer"
-                }
-            }
-          },
-          "valid": true
+        "valid": true
+      },
+      {
+        "description": "addP === false && !props && !patternProps && minProperties",
+        "schema": {
+          "type": "object",
+          "minProperties": 2,
+          "additionalProperties": false
+        },
+        "throws": "missing properties for:\n[\\s\\S]+? in \\/"
+      },
+      {
+        "description": "addP === undef || props",
+        "schema": {
+          "type": "object",
+          "minProperties": 2,
+          "properties": {
+              "count": {
+                  "type": "integer"
+              }
+          }
         },
-        {
+        "valid": true
+      },
+      {
         "description": "should skip some non-required properties",
         "schema": {
           "type": "object",
diff --git a/ts/class/OptionRegistry.ts b/ts/class/OptionRegistry.ts
index 3994c37e56471ba7e7ae330e898550d12d01b8df..bc52f0bc3d40dd65d82080bc4efa93155985f950 100644
--- a/ts/class/OptionRegistry.ts
+++ b/ts/class/OptionRegistry.ts
@@ -23,6 +23,7 @@ class OptionRegistry extends Registry<Option> {
     data['failOnInvalidFormat'] = true;
 
     data['alwaysFakeOptionals'] = false;
+    data['optionalsProbability'] = 0.0;
     data['useDefaultValue'] = false;
     data['requiredOnly'] = false;
 
diff --git a/ts/types/array.ts b/ts/types/array.ts
index 76c7679546f8e726eab87f404f7bb2a46bbb5f1f..ee38168626ab0afde1824c0803533096791f79fc 100644
--- a/ts/types/array.ts
+++ b/ts/types/array.ts
@@ -79,8 +79,10 @@ var arrayType: FTypeGenerator = function arrayType(value: IArraySchema, path: Sc
     }
   }
 
-  var length: number = (maxItems != null && optionAPI('alwaysFakeOptionals')) ?
-    maxItems : random.number(minItems, maxItems, 1, 5),
+  var optionalsProbability = optionAPI('alwaysFakeOptionals') === true ? 1.0 : optionAPI('optionalsProbability');
+  var length: number = (maxItems != null && optionalsProbability)
+    ? Math.round(maxItems * optionalsProbability)
+    : random.number(minItems, maxItems, 1, 5),
     // TODO below looks bad. Should additionalItems be copied as-is?
     sample: Object = typeof value.additionalItems === 'object' ? value.additionalItems : {};
 
diff --git a/ts/types/object.ts b/ts/types/object.ts
index 1690e86e0a4c27800cbe8887d9396281c2f4f575..137399338374d8e3cca652178b052e6ebf746a08 100644
--- a/ts/types/object.ts
+++ b/ts/types/object.ts
@@ -18,6 +18,11 @@ var objectType: FTypeGenerator = function objectType(value: IObjectSchema, path,
 
     var propertyKeys = Object.keys(properties);
     var patternPropertyKeys = Object.keys(patternProperties);
+    var optionalProperties = propertyKeys.concat(patternPropertyKeys).reduce(function(_response, _key) {
+        if (requiredProperties.indexOf(_key) === -1) _response.push(_key);
+        return _response;
+    }, []);
+    var allProperties = requiredProperties.concat(optionalProperties);
 
     var additionalProperties = allowsAdditional
       ? (value.additionalProperties === true ? {} : value.additionalProperties)
@@ -43,22 +48,20 @@ var objectType: FTypeGenerator = function objectType(value: IObjectSchema, path,
         return traverseCallback(props, path.concat(['properties']), resolve);
     }
 
+    var optionalsProbability = optionAPI('alwaysFakeOptionals') === true ? 1.0 : optionAPI('optionalsProbability');
+    var ignoreProperties = optionAPI('ignoreProperties') || [];
 
     var min = Math.max(value.minProperties || 0, requiredProperties.length);
-    var max = Math.max(value.maxProperties || random.number(min, propertyKeys.length));
+    var max = Math.max(value.maxProperties || allProperties.length);
 
-    random.shuffle(patternPropertyKeys).forEach(function(_key) {
-        if (requiredProperties.indexOf(_key) === -1) {
-            requiredProperties.push(_key);
-        }
+    var neededExtras = Math.round((min - requiredProperties.length) + optionalsProbability * (max - min));
+    var extraPropertiesRandomOrder = random.shuffle(optionalProperties).slice(0, neededExtras);
+    var extraProperties = optionalProperties.filter(function(_item) {
+        return extraPropertiesRandomOrder.indexOf(_item) !== -1;
     });
 
-    var fakeOptionals = optionAPI('alwaysFakeOptionals');
-    var ignoreProperties = optionAPI('ignoreProperties') || [];
-
     // properties are read from right-to-left
-    var _props = fakeOptionals ? propertyKeys
-      : requiredProperties.slice(0, max);
+    var _props = requiredProperties.concat(extraProperties).slice(0, max);
 
     var skipped = [];
     var missing = [];