Quick actions

cmd+k|ctrl+k

Navigation

Languages

Json to C#

Snippet info

Language

JavaScript

Visibility

public

Author

evine

Created

2018-12-17T14:10:29Z

Updated

2022-12-09T09:28:33.41669Z

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;
}
INFO