Last active
November 1, 2021 19:45
-
-
Save mahsumurebe/073a7cac94849cbb8ca69259ee68689c to your computer and use it in GitHub Desktop.
JSON to dart class, json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type convertFN = (key: string, value: any) => void; | |
type convertibleTypes = (key: string, value: any) => void | string | number; | |
const convertibleTypeList = { | |
Number: (_key: string, value: any) => value % 1 === 0 ? 'int' : 'double', | |
String: 'String', | |
Boolean: 'bool', | |
Undefined: 'null', | |
Null: 'null', | |
}; | |
function firstUp(str: string) { | |
let arr = str.split(''); | |
arr[0] = arr[0].toUpperCase(); | |
return arr.join(''); | |
} | |
function camelize(str, firstUpper = false) { | |
const regExp = /[-_]\w/ig; | |
const camelize = str.replace(regExp, (match) => { | |
return match[1].toUpperCase(); | |
}); | |
if (firstUpper) | |
return firstUp(camelize); | |
return camelize; | |
} | |
function getType(x: any) { | |
// @ts-ignore | |
return Object.prototype.toString.call(x).match(/\[object (.*)\]/)[1]; | |
} | |
function getT(variableValue: any, key, value) { | |
let t = convertibleTypeList[getType(variableValue)] ?? firstUp(typeof variableValue); | |
if (getType(t) === 'Function') | |
return t(key, value); | |
return t; | |
} | |
function _toClass(obj: { [key: string]: any }[], className = 'CLASS_NAME', parentClass = undefined): string { | |
const variableUsesCount: { [key: string]: number } = {}; | |
const variables: { [variableName: string]: { isNullable: boolean, type: string, name: string, class: boolean } } = {}; | |
const nullKeys = []; | |
let anotherClasses = {}; | |
for (const objElement of obj) { | |
for (const variableName of Object.keys(objElement)) { | |
variableUsesCount[variableName] = (variableUsesCount[variableName] ?? 0) + 1; | |
const variableValue = objElement[variableName]; | |
const type = getT(variableValue, variableName, variableValue); | |
let isNullable = variableValue == null || Object.keys(objElement).length > variableUsesCount[variableName]; | |
if (type === 'Object' && !Array.isArray(variableValue)) { | |
const cName = camelize((parentClass ? parentClass+'_':'')+variableName, true); | |
anotherClasses[cName]=(_toClass([variableValue], camelize(variableName, true), cName)); | |
variables[variableName] = { | |
name: camelize(variableName, false), | |
isNullable, | |
type: cName, | |
class: true, | |
}; | |
} else if (Array.isArray(variableValue)) { | |
if (variableValue.length === 0) { | |
variables[variableName] = { | |
class: false, | |
name: camelize(variableName, false), | |
type: `List<dynamic>`, | |
isNullable: false, | |
}; | |
} else { | |
let type = getT(variableValue[0], variableValue[0], variableName); | |
let isNullable = variableValue.some(o => o === null || o === undefined); | |
if (type !== 'Object') { | |
variables[variableName] = { | |
class: false, | |
name: camelize(variableName, false), | |
type: type === 'null' ? variables[variableName]?.type ?? 'dynamic' : `List<${type}>`, | |
isNullable, | |
}; | |
} else { | |
const cName = camelize((parentClass ? parentClass+'_':'')+variableName, true); | |
anotherClasses[cName]=(toClass(variableValue, cName,cName)); | |
variables[variableName] = { | |
class: true, | |
name: variableName, | |
type: cName, | |
isNullable, | |
}; | |
} | |
} | |
} else { | |
if (isNullable) | |
nullKeys.push(variableName); | |
variables[variableName] = { | |
class: false, | |
name: camelize(variableName), | |
isNullable, | |
type: type === 'null' ? variables[variableName]?.type ?? 'dynamic' : type, | |
}; | |
} | |
} | |
} | |
return ` | |
${Object.values(anotherClasses).join('\n')} | |
class ${camelize(className, true)} { | |
${Object.keys(variables).map(variableName => { | |
const variable = variables[variableName]; | |
const out = []; | |
out.push(variable.type + (variable.isNullable ? '?' : '')); | |
out.push(variable.name); | |
return out.join(' '); | |
}).join(';\n ') + (Object.keys(variables).length > 0 ? ';' : '')} | |
${camelize(className, true)}.fromJSON(Map<String, dynamic> data): | |
${Object.keys(variables).map(variableName => { | |
const variable = variables[variableName]; | |
const out = []; | |
out.push(variable.name); | |
out.push('='); | |
if (variable.class) { | |
if (variable.isNullable) { | |
out.push(`data['${variableName}'] == null ? ${variable.type}.fromJSON(data['${variableName}']) : null`); | |
} else { | |
out.push(`${variable.type}.fromJSON(data['${variableName}'])`); | |
} | |
} else { | |
out.push(`data['${variableName}']`); | |
} | |
return out.join(' '); | |
}).join(',\n ')}; | |
} | |
`.replace(/\n+/g,'\n'); | |
} | |
function toClass(arg: any, className = 'CLASS_NAME', parent=null) { | |
if (Array.isArray(arg)) { | |
return _toClass(arg, className, parent); | |
} else if (typeof arg === 'object') { | |
return _toClass([arg], className, parent); | |
} else { | |
throw Error('Param must be JSON object or array.'); | |
} | |
} | |
const json = {} | |
console.log(toClass(json, 'Template')); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment