Skip to content

Commit 6a19307

Browse files
author
Bruno Herfst
committed
Add aes.patch.json.instantiate
1 parent b693a10 commit 6a19307

File tree

6 files changed

+253
-6
lines changed

6 files changed

+253
-6
lines changed

aes/patch/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Extensions to existing objects
6464
- [ ] [JSON.cycle](json.cycle)
6565
- [ ] [JSON.equals](json.equals)
6666
- [ ] [JSON.file](json.file)
67-
- [ ] [JSON.instantiate](json.instantiate)
67+
- [x] [JSON.instantiate](json.instantiate)
6868
- [ ] [JSON.parseRecurse](json.parserecurse)
6969
- [ ] [JSON.parseState](json.parsestate)
7070
- [ ] [JSON.validate](json.validate)

aes/patch/json.instantiate/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,31 @@ Source: [tomarad/JSON-Schema-Instantiator](https://github.com/tomarad/JSON-Schem
1616

1717
#include 'node_modules/@extendscript/aes.patch.json.instantiate/instantiate.js'
1818

19+
## Use
20+
21+
var schema = {
22+
"type": "object",
23+
"properties": {
24+
"title": {
25+
"type": "string",
26+
"default": "Example"
27+
},
28+
"description": {
29+
"type": "string"
30+
}
31+
},
32+
"required": ["title"]
33+
};
34+
35+
instance = JSON.instantiate(schema);
36+
// instance === { title: "Example", description: "" }
37+
38+
instance = JSON.instantiate(schema, {requiredPropertiesOnly: false});
39+
// instance === { title: "Example", description: "" }
40+
41+
instance = JSON.instantiate(schema, {requiredPropertiesOnly: true});
42+
// instance === { title: "Example" }
43+
1944
## Test
2045

2146
You can test the code against a range of [targets](https://github.com/nbqx/fakestk/blob/master/resources/versions.json):
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,195 @@
11

22
// JSON is a peer dependency so will be loaded
3+
4+
if (typeof JSON.instantiate !== 'function') {
5+
6+
/*
7+
8+
JSON Schema Instantiator
9+
10+
https://github.com/tomarad/JSON-Schema-Instantiator
11+
12+
The MIT License (MIT)
13+
14+
Copyright (c) 2015 Tom Arad
15+
16+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
17+
and associated documentation files (the "Software"), to deal in the Software without restriction,
18+
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
19+
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
20+
subject to the following conditions:
21+
22+
The above copyright notice and this permission notice shall be included in all copies
23+
or substantial portions of the Software.
24+
25+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
26+
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
27+
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
28+
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30+
31+
*/
32+
33+
JSON.instantiate = function(schema, options) {
34+
'use strict';
35+
36+
options = options || {};
37+
38+
// Set requiredPropertiesOnly to true if not defined
39+
if ( typeof options.requiredPropertiesOnly === 'undefined') options.requiredPropertiesOnly = true;
40+
41+
// The JSON Object that defines the default values of certain types.
42+
var typesInstantiator = {
43+
'string': '',
44+
'number': 0,
45+
'integer': 0,
46+
'null': null,
47+
'boolean': false, // Always stay positive?
48+
'object': { }
49+
};
50+
51+
/**
52+
* Checks whether a variable is a primitive.
53+
* @param obj - an object.
54+
* @returns {boolean}
55+
*/
56+
function isPrimitive(obj) {
57+
var type = obj.type;
58+
59+
return typesInstantiator[type] !== undefined;
60+
};
61+
62+
/**
63+
* Checks whether a property is on required array.
64+
* @param property - the property to check.
65+
* @param requiredArray - the required array
66+
* @returns {boolean}
67+
*/
68+
function isPropertyRequired(property, requiredArray) {
69+
var found = false;
70+
requiredArray = requiredArray || [];
71+
requiredArray.forEach(function(requiredProperty) {
72+
if (requiredProperty === property) {
73+
found = true;
74+
};
75+
});
76+
return found;
77+
};
78+
79+
80+
function shouldVisit(property, obj, options) {
81+
return (!options.requiredPropertiesOnly) || (options.requiredPropertiesOnly && isPropertyRequired(property, obj.required));
82+
};
83+
84+
/**
85+
* Instantiate a primitive.
86+
* @param val - The object that represents the primitive.
87+
* @returns {*}
88+
*/
89+
function instantiatePrimitive(val) {
90+
var type = val.type;
91+
92+
// Support for default values in the JSON Schema.
93+
if (val.default) {
94+
return val.default;
95+
};
96+
97+
return typesInstantiator[type];
98+
};
99+
100+
/**
101+
* Checks whether a variable is an enum.
102+
* @param obj - an object.
103+
* @returns {boolean}
104+
*/
105+
function isEnum(obj) {
106+
return Object.prototype.toString.call(obj.enum) === '[object Array]';
107+
};
108+
109+
/**
110+
* Extracts the type of the object.
111+
* If the type is an array, set type to first in list of types.
112+
* If obj.type is not overridden, it will fail the isPrimitive check.
113+
* Which internally also checks obj.type.
114+
* @param obj - An object.
115+
*/
116+
function getObjectType(obj) {
117+
// Check if type is array of types.
118+
if (Array.isArray(obj.type)) {
119+
obj.type = obj.type[0];
120+
};
121+
122+
return obj.type;
123+
};
124+
125+
/**
126+
* Instantiate an enum.
127+
* @param val - The object that represents the primitive.
128+
* @returns {*}
129+
*/
130+
function instantiateEnum(val) {
131+
// Support for default values in the JSON Schema.
132+
if (val.default) {
133+
return val.default;
134+
};
135+
if (!val.enum.length) {
136+
return undefined;
137+
};
138+
return val.enum[0];
139+
};
140+
141+
/**
142+
* Visits each sub-object using recursion.
143+
* If it reaches a primitive, instantiate it.
144+
* @param obj - The object that represents the schema.
145+
* @param name - The name of the current object.
146+
* @param data - The instance data that represents the current object.
147+
*/
148+
function visit(obj, name, data) {
149+
if (!obj) {
150+
return;
151+
};
152+
153+
var i;
154+
var type = getObjectType(obj);
155+
156+
// We want non-primitives objects (primitive === object w/o properties).
157+
if (type === 'object' && obj.properties) {
158+
data[name] = data[name] || { };
159+
160+
// Visit each property.
161+
for (var property in obj.properties) {
162+
if (obj.properties.hasOwnProperty(property)) {
163+
if (shouldVisit(property, obj, options)) {
164+
visit(obj.properties[property], property, data[name]);
165+
};
166+
};
167+
};
168+
} else if (obj.allOf) {
169+
for (i = 0; i < obj.allOf.length; i++) {
170+
visit(obj.allOf[i], name, data);
171+
};
172+
} else if (type === 'array') {
173+
data[name] = [];
174+
var len = 0;
175+
if (obj.minItems || obj.minItems > 0) {
176+
len = obj.minItems;
177+
};
178+
179+
// Instantiate 'len' items.
180+
for (i = 0; i < len; i++) {
181+
visit(obj.items, i, data[name]);
182+
};
183+
} else if (isEnum(obj)) {
184+
data[name] = instantiateEnum(obj);
185+
} else if (isPrimitive(obj)) {
186+
data[name] = instantiatePrimitive(obj);
187+
};
188+
};
189+
190+
var data = {};
191+
visit(schema, 'kek', data);
192+
return data['kek'];
193+
};
194+
195+
};

aes/patch/json.instantiate/package.json

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,21 @@
2424
"bugs": {
2525
"url": "https://github.com/ExtendScript/extendscript-modules/issues"
2626
},
27+
"contributors": [
28+
"Tom Arad <[email protected]> (https://github.com/tomarad/JSON-Schema-Instantiator)"
29+
],
2730
"homepage": "https://github.com/ExtendScript/extendscript-modules#readme",
2831
"devDependencies": {
32+
"@extendscript/aes.patch.json": ">=1.0.0",
33+
"@extendscript/aes.patch.array.foreach": ">=2.0.0",
34+
"@extendscript/aes.patch.array.isarray": ">=2.0.0",
35+
"@extendscript/tap-es": ">=1.0.5",
2936
"build-node-venv": "^1.0.3",
30-
"minimist": "^1.2.0",
31-
"@extendscript/tap-es": ">=1.0.5"
37+
"minimist": "^1.2.0"
3238
},
3339
"peerDependencies": {
34-
"@extendscript/aes.patch.json": "^1.0.0"
40+
"@extendscript/aes.patch.json": ">=1.0.0",
41+
"@extendscript/aes.patch.array.foreach": ">=2.0.0",
42+
"@extendscript/aes.patch.array.isarray": ">=2.0.0"
3543
}
3644
}

aes/patch/json.instantiate/test/results_log.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ As tests may be run by different people on different platforms the results are l
44

55
## json.instantiate.js
66

7-
> Version 0
7+
> Version 1.0.0
8+
9+
- ✔ Darwin indesign-13: json.instantiate [pass: 1, fail: 0]
Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
#include '../node_modules/@extendscript/aes.patch.array.foreach/foreach.js'
2+
#include '../node_modules/@extendscript/aes.patch.array.isarray/isarray.js'
3+
#include '../node_modules/@extendscript/aes.patch.json/json.js'
14
#include '../instantiate.js'
25

3-
$.writeln( undefined === true);
6+
var schema = {
7+
"type": "object",
8+
"properties": {
9+
"name": { "type": "string", "default": "New Preset" },
10+
"bool": { "type": ["null", "boolean"] },
11+
"obj": { "type": "object",
12+
"properties": {
13+
"x": { "type": "number", "default": 0 },
14+
"y": { "type": "number", "default": 0 }
15+
}
16+
}
17+
}
18+
};
19+
20+
var preset = JSON.instantiate( schema, {requiredPropertiesOnly: false} );
21+
22+
$.writeln( JSON.stringify(preset) === '{"name":"New Preset","bool":null,"obj":{"x":0,"y":0}}');

0 commit comments

Comments
 (0)