Skip to content

Instantly share code, notes, and snippets.

@KaNiShi
Created February 20, 2019 15:13
Show Gist options
  • Save KaNiShi/cfa07e956021851ecf1b6756178865b1 to your computer and use it in GitHub Desktop.
Save KaNiShi/cfa07e956021851ecf1b6756178865b1 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Json2KotlinxSerializationDataClass</title>
<style>
textarea {
width: 48vw;
height: 32vw;
}
</style>
<script>
window.onload = function () {
document.getElementById('convert').onclick = function () {
let jsonValue = document.getElementById('json').value;
let kotlinArea = document.getElementById('kotlin');
try {
let json = JSON.parse(jsonValue);
classCount = 1;
if (!Array.isArray(json)) {
let kotlinClass = `import kotlinx.serialization.SerialName\nimport kotlinx.serialization.Serializable\n\n`;
kotlinClass += createObjectClass(json);
kotlinArea.textContent = kotlinClass;
} else {
kotlinArea.textContent = 'エラー\n未対応の形式です'
}
} catch (e) {
kotlinArea.textContent = `エラー\n${e}`;
}
}
}
let className = 'Untitled';
let classCount = 1;
let classTab = ' ';
const KOTLIN_CLASS_ANY = 'Any';
const KOTLIN_CLASS_BOOLEAN = 'Boolean';
const KOTLIN_CLASS_CHAR = 'Char';
const KOTLIN_CLASS_BYTE = 'Byte';
const KOTLIN_CLASS_INT = 'Int';
const KOTLIN_CLASS_LONG = 'Long';
const KOTLIN_CLASS_FLOAT = 'Float';
const KOTLIN_CLASS_DOUBLE = 'Double';
const KOTLIN_CLASS_STRING = 'String';
const KOTLIN_CLASS_LIST = 'List';
function createObjectClass(items) {
let classData = { className: `${className}${classCount++}`, params: [], otherClass: [] };
for (let index in items) {
let item = items[index];
switch (typeof item) {
case 'boolean':
classData.params.push({ name: index, type: KOTLIN_CLASS_BOOLEAN, nullable: false });
break;
case 'number':
if (Number.isInteger(item)) {
if (item > 2147483647 || item < -2147483648) {
classData.params.push({ name: index, type: KOTLIN_CLASS_LONG, nullable: false });
} else {
classData.params.push({ name: index, type: KOTLIN_CLASS_INT, nullable: false });
}
} else {
classData.params.push({ name: index, type: KOTLIN_CLASS_DOUBLE, nullable: false });
}
break;
case 'string':
classData.params.push({ name: index, type: KOTLIN_CLASS_STRING, nullable: false });
break;
case 'object':
if (Array.isArray(item)) {
let listClassData = createArrayClass(item);
classData.params.push({ name: index, type: `${KOTLIN_CLASS_LIST}<${listClassData.className}${listClassData.nullable?'?':''}>`, nullable: false });
if(listClassData.otherClass != null) classData.otherClass.push(listClassData.otherClass);
} else {
if (item === null) {
classData.params.push({ name: index, type: KOTLIN_CLASS_ANY, nullable: true });
} else {
classData.params.push({ name: index, type: `${className}${classCount}`, nullable: false });
classData.otherClass.push(createObjectClass(item));
}
}
break;
}
}
let kotlinClass = `@Serializable\ndata class ${classData.className}(`;
for (let member of classData.params) {
kotlinClass += `\n${createMemberParam(member)},`;
}
kotlinClass = kotlinClass.substring(0, kotlinClass.length - 1);
kotlinClass += '\n)\n';
for (let otherClass of classData.otherClass) {
kotlinClass += `\n${otherClass}\n`;
}
return kotlinClass;
}
function createArrayClass(items) {
let classData = { className: null, dataClass: null, nullable: false, otherClass: null };
for (let item of items) {
switch (typeof item) {
case 'boolean':
classData.className = checkClassMache(classData.className, KOTLIN_CLASS_BOOLEAN);
break;
case 'number':
if (Number.isInteger(item)) {
if (item > 2147483647 || item < -2147483648) {
classData.className = checkClassMache(classData.className, KOTLIN_CLASS_LONG);
} else {
classData.className = checkClassMache(classData.className, KOTLIN_CLASS_INT);
}
} else {
classData.className = checkClassMache(classData.className, KOTLIN_CLASS_DOUBLE);
}
break;
case 'string':
classData.className = checkClassMache(classData.className, KOTLIN_CLASS_STRING);
break;
case 'object':
if (Array.isArray(item)) {
} else if (item != null) {
} else {
classData.nullable = true;
}
break;
}
}
return classData;
}
function checkClassMache(currentClass, targetClass) {
if (currentClass == null) {
return targetClass;
} else if (currentClass != targetClass) {
if (targetClass == KOTLIN_CLASS_LONG) {
if (currentClass == KOTLIN_CLASS_INT) {
return targetClass
} else {
return KOTLIN_CLASS_ANY
}
} else if (targetClass == KOTLIN_CLASS_DOUBLE) {
if (currentClass == KOTLIN_CLASS_INT || currentClass == KOTLIN_CLASS_LONG || currentClass == KOTLIN_CLASS_FLOAT) {
return targetClass
} else {
return KOTLIN_CLASS_ANY
}
} else {
return KOTLIN_CLASS_ANY;
}
} else {
return currentClass;
}
}
function createMemberParam(params) {
return `${classTab}@SerialName("${params.name}")\n${classTab}val ${createMemberName(params.name)}: ${params.type}${params.nullable ? '?' : ''}`;
}
function createMemberName(name) {
let splitName = name.split('_');
let memberName = splitName[0];
for (let i = 1; i < splitName.length; i++) {
let text = splitName[i];
memberName += text.charAt(0).toUpperCase() + text.slice(1);
}
return memberName;
}
</script>
</head>
<body>
<h1>Json2KotlinxSerializationDataClass</h1>
<div><textarea id="json" placeholder="Json"></textarea></div>
<div><button id="convert">↓</button></div>
<div><textarea id="kotlin" placeholder="Kotlin" readonly></textarea></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment