Guest User

Untitled

a guest
Jul 12th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.78 KB | None | 0 0
  1. const
  2. /*
  3. Node Internals
  4. */
  5. UTIL = require('util'),
  6.  
  7. /*
  8. Npm Third Party
  9. */
  10. _ = require('lodash'),
  11.  
  12. /*
  13. Global Variables
  14. */
  15. TYPE_MAP = {
  16. string : 'string',
  17. number : 'number',
  18. boolean : 'boolean',
  19. array : 'array',
  20. object : 'object'
  21. },
  22. PRIM_ARRAY = [
  23. 'string',
  24. 'number',
  25. 'boolean'
  26. ];
  27.  
  28. class jsonValidator {
  29.  
  30. validate(schema, jsonData) {
  31.  
  32. if(typeof jsonData !== TYPE_MAP.object)
  33. return "input not a valid json";
  34.  
  35. try{
  36. checkLevelKeys(schema.properties, jsonData);
  37. } catch (errorMessage) {
  38. return errorMessage.message;
  39. }
  40.  
  41. return true;
  42. }
  43.  
  44. isValidJsonSchema(schema) {
  45. if(!schema.properties || !UTIL.isArray(schema.properties))
  46. throw new Error('Not a valid schema!');
  47.  
  48. const
  49. mandatorySchemaPropertyKeys = [
  50. 'keyName',
  51. 'keyType'
  52. ];
  53. try{
  54. schema.properties.forEach( (property) => {
  55.  
  56. mandatorySchemaPropertyKeys.forEach( (propertyKey) => {
  57. if(!_.get(property, propertyKey, null))
  58. throw new Error(`${propertyKey} missing`);
  59. });
  60.  
  61. if(property.properties)
  62. return isValidJsonSchema(property);
  63. });
  64. } catch (error){
  65. return false;
  66. }
  67.  
  68. return true;
  69. }
  70. }
  71.  
  72. /*
  73. Util unexposed functions
  74. */
  75.  
  76. function checkLevelKeys(properties, jsonData, keyParentLocationArray=[]) {
  77. if(UTIL.isArray(jsonData)){
  78. jsonData.forEach( (dataAtom, index) => {
  79. properties.forEach( (property) => {
  80. const
  81. keyName = _.get(property, 'keyName', ''),
  82. keyType = _.get(property, 'keyType', ''),
  83. isMandatory = _.get(property, 'isMandatory', false),
  84. valueReceived = _.get(dataAtom, keyName, null),
  85. keyLocationArray = _.cloneDeep(keyParentLocationArray);
  86.  
  87. keyLocationArray.push(index);
  88. keyLocationArray.push(keyName);
  89.  
  90.  
  91. if(valueReceived || valueReceived === false)
  92. validateType(property, keyType, valueReceived, keyLocationArray);
  93. else if(isMandatory)
  94. throw new Error(`${keyLocationArrayStringCreator(keyLocationArray)} is missing`);
  95. });
  96. });
  97. } else{
  98. properties.forEach( (property) => {
  99. const
  100. keyName = _.get(property, 'keyName', ''),
  101. keyType = _.get(property, 'keyType', ''),
  102. isMandatory = _.get(property, 'isMandatory', false),
  103. valueReceived = _.get(jsonData, keyName, null),
  104. keyLocationArray = _.cloneDeep(keyParentLocationArray);
  105.  
  106. keyLocationArray.push(keyName);
  107.  
  108.  
  109. if(valueReceived || valueReceived === false)
  110. validateType(property, keyType, valueReceived, keyLocationArray);
  111. else if(isMandatory)
  112. throw new Error(`${keyLocationArrayStringCreator(keyLocationArray)} is missing`);
  113. });
  114. }
  115. }
  116.  
  117. function validateType(property, keyType, valueReceived, keyLocationArray){
  118. /*
  119. In case there is an error
  120. we are already prepared
  121. */
  122. const
  123. errorMessage = makeTypeErrorString(keyLocationArray, keyType),
  124. errorKeyType = makeTypeErrorString(keyType);
  125.  
  126. switch(keyType){
  127.  
  128. case TYPE_MAP.string :
  129.  
  130. if(typeof valueReceived !== TYPE_MAP.string)
  131. throw new Error(errorMessage);
  132.  
  133. break;
  134.  
  135. case TYPE_MAP.number :
  136.  
  137. if(typeof valueReceived !== TYPE_MAP.number)
  138. throw new Error(errorMessage);
  139.  
  140. break;
  141.  
  142. case TYPE_MAP.boolean :
  143.  
  144. if(typeof valueReceived !== TYPE_MAP.boolean)
  145. throw new Error(errorMessage);
  146.  
  147. break;
  148.  
  149. case TYPE_MAP.array :
  150.  
  151. if(!UTIL.isArray(valueReceived))
  152. throw new Error(errorMessage);
  153. if (property.type)
  154. checkValuesInAnArray(property.type, valueReceived, keyLocationArray);
  155. else if(property.properties)
  156. checkLevelKeys(property.properties, valueReceived, keyLocationArray, true);
  157.  
  158. break;
  159.  
  160. case TYPE_MAP.object :
  161.  
  162. if( (typeof valueReceived !== TYPE_MAP.object) || (UTIL.isArray(valueReceived)) )
  163. throw new Error(errorMessage);
  164.  
  165. if(property.properties)
  166. checkLevelKeys(property.properties, valueReceived, keyLocationArray);
  167.  
  168. break;
  169.  
  170. default :
  171.  
  172. throw new Error(errorKeyType);
  173. }
  174. }
  175.  
  176. function makeTypeErrorString(keyLocationArray, expectedKeyType){
  177. if(expectedKeyType)
  178. return `${keyLocationArrayStringCreator(keyLocationArray)} was expected to be a ${expectedKeyType}`;
  179. else
  180. expectedKeyType = keyLocationArray
  181. return `${expectedKeyType} not supported in validator`;
  182. }
  183.  
  184. function keyLocationArrayStringCreator(keyLocationArray){
  185. return keyLocationArray.join('.');
  186. }
  187.  
  188. function checkValuesInAnArray(type, data, keyLocationArray){
  189.  
  190. if(!PRIM_ARRAY.includes(type))
  191. throw new Error (`${type} not supported for primitive arrays`);
  192.  
  193. data.forEach( (dataAtom, index) => {
  194. if(typeof dataAtom !== type){
  195. keyLocationArray.push(index);
  196. throw new Error (makeTypeErrorString(keyLocationArray, type));
  197. }
  198. });
  199. }
  200.  
  201. module.exports = jsonValidator;
  202.  
  203.  
  204. (() => {
  205. const
  206. mySchema = {
  207. properties : [{
  208. keyName : 'name',
  209. keyType : 'string',
  210. isMandatory : true
  211. },{
  212. keyName : 'someBool',
  213. keyType : 'boolean',
  214. isMandatory : true
  215. },{
  216. keyName : 'age',
  217. keyType : 'number',
  218. isMandatory : true
  219. },{
  220. keyName : 'day',
  221. keyType : 'string',
  222. isMandatory : false
  223. },{
  224. keyName : 'sArray',
  225. keyType : 'array',
  226. isMandatory : true,
  227. type : 'boolean',
  228. },{
  229. keyName : 'a',
  230. keyType : 'array',
  231. isMandatory : true,
  232. properties : [{
  233. keyName : 'name',
  234. keyType : 'string',
  235. isMandatory : true
  236. },{
  237. keyName : 'age',
  238. keyType : 'number',
  239. isMandatory : true
  240. },{
  241. keyName : 'dummy',
  242. keyType : 'array',
  243. isMandatory : true,
  244. properties : [{
  245. keyName : 'r',
  246. keyType : 'string',
  247. isMandatory : true
  248. }]
  249. }]
  250. },{
  251. keyName : 'ab',
  252. keyType : 'object',
  253. isMandatory : true,
  254. properties : [{
  255. keyName : 'name',
  256. keyType : 'string',
  257. isMandatory : true
  258. },{
  259. keyName : 'age',
  260. keyType : 'number',
  261. isMandatory : true
  262. }]
  263. }]
  264. },
  265. myTestJson = {
  266. name : 'Vidur Khanna',
  267. someBool : false,
  268. age : 23,
  269. sArray : [true, false],
  270. a : [{
  271. name : 'dasdas',
  272. age : 23,
  273. dummy : [{
  274. r : 'sdagdjafsd'
  275. }]
  276. }],
  277. ab : {
  278. name : 'Vidur Khanna',
  279. age : 23,
  280. }
  281. },
  282. jV = new jsonValidator();
  283.  
  284. console.log('isJsonValid -> ', jV.validate(mySchema, myTestJson));
  285. })();
Add Comment
Please, Sign In to add comment