const fs = require("fs");
const json = fs.readFileSync("/dev/stdin", "utf-8");
const data = JSON.parse(json);
const r = getStructure(data);
printCode(r, "Base");
function getCsType(a) {
if (a === null) {
return "null";
} else if (a === undefined) {
return "undefined";
} else if (typeof a === "number") {
return Number.isInteger(a) ? "int" : "double";
} else if (typeof a === "boolean") {
return "bool";
} else if (typeof a === "string") {
return "string?";
}
return typeof a;
}
function getStructure(a) {
const t = getCsType(a);
if (a === null) {
return t;
} else if (Array.isArray(a)) {
let r = {};
for(const v of a) {
if (typeof v == "object") {
for(const k in v) {
const newType = getStructure(v[k]);
// Fix: Be smarter in how different types are merged.
// Currently C# can be invalid for union types.
// Eg: int | class or between multiple classes
if(r[k] && (newType === "null" || newType === "undefined")) {
} else if(r[k] == "double" && newType == "int") {
} else {
r[k] = newType;
}
}
} else {
r = getCsType(v);
}
}
return {type: "array", obj: r};
} else if (typeof a === "object") {
const r = {};
for(const k in a) {
r[k] = getStructure(a[k]);
}
return {type: "object", obj: r};
}
return t;
}
function printCode(a, name) {
const newClasses = [];
let i = 0;
console.log(`public class ${toTileCase(name)}`);
console.log(`{`);
for(const v in a.obj) {
if (i != 0) {
console.log();
}
i += 1;
const prop = toTileCase(v);
console.log(`\t[JsonPropertyName("${v}")]`);
if (typeof a.obj[v] == "object" && a.obj[v].type == "array") {
if(typeof a.obj[v].obj == "object") {
newClasses.push({obj: a.obj[v], name: v});
console.log(`\tpublic List<${prop}>? ${prop} { get; set; }`);
} else {
let type = a.obj[v].obj;
if (type == "string?") {
type = "string";
}
console.log(`\tpublic List<${type}>? ${prop} { get; set; }`);
}
} else if (typeof a.obj[v] == "object" && a.obj[v].type == "object") {
newClasses.push({obj: a.obj[v], name: v});
console.log(`\tpublic ${prop}? ${prop} { get; set; }`);
} else {
console.log(`\tpublic ${a.obj[v]} ${prop} { get; set; }`);
}
}
console.log(`}`);
console.log();
for(const c of newClasses) {
printCode(c.obj, c.name);
}
}
function toTileCase(s) {
let result = "";
let nextUpper = true;
for(let i = 0; i < s.length; ++i) {
if(s[i] === "_" || s[i] === "-") {
nextUpper = true;
} else if(nextUpper) {
result += s[i].toUpperCase();
nextUpper = false;
} else {
result += s[i];
}
}
return result;
}