如何將JavaScript轉化成Swift?(三)

LuckyRoc發表於2019-04-08

本文銜接 如何將JavaScript轉化成Swift?(二) ,主要是關於將JavaScript的解析Json程式碼翻譯到Swift當中?(如何將一段Json字串自動生成HandyJson格式的Model類)

將JavaScript的解析JSON程式碼翻譯到Swift

JSON解析

{
    "error":0,
    "msg":"success",
    "data":[
        {
            "id":27,
            "name":"協議和幫助",
            "sname":"xy",
            "parent_id":"0",
            "flag":"0",
            "created":"2017-01-15 09:47:09",
            "tag":[
                1,
                5
            ],
            "dated":"2017-01-15 16:31:32"
        }
    ]
}
複製程式碼

JavaScript 解析Json

JavaScript 中獲取 "name" 只需要一行程式碼即可

var jsonObj = str.parseJSON();
jsonObj.data[0].name
複製程式碼

Swift 解析 Json

Swift中常用的JOSN解析庫有 HandyJson、ObjectMapper、SwiftyJson

SwiftyJson 不要預先定義 Model Class 檔案,但是不支援轉Mode,而且解析Json的語法和Js差異較大;

ObjectMapper Model類必須實現Mappable協議,即實現init和mapping函式;適合跟Alamofire配合。但是mapping函式過於臃腫耗時;

HandyJson 採用Swift反射+記憶體賦值的方式來構造Model例項,寫法簡便且能支援json和model互轉的需求,而且一直在更新維護,解析Json的語法和Js差異較小;

結論: 採用HandyJson來進行Json解析!

如何生成HandyJson所需要的Model類?

這裡就直接貼程式碼了。。。


// 生成Swift的Model檔案
var generateCode = function (jsonString, className) {
    var k = "";

    // 首字母大寫
    var toUpperVar = function (a) {
        return a.replace(/\b[a-z]/g, function (a) {
            return a.toUpperCase()
        })
    };

    // 小寫
    var toLowerVar = function (a) {
        return a.replace(/\b[a-z]/g, function (a) {
            return a.toLowerCase()
        })
    };

    // 判斷是否有巢狀的Model
    var q = function (a) {
        // 判斷是否是一個陣列
        return a instanceof Object ? a.constructor.prototype.hasOwnProperty("push") : !1
    };

    var r = function (a) {
        // 判斷是否是一個陣列
        return a instanceof Object ? !a.constructor.prototype.hasOwnProperty("push") : !1
    };

    // 生成 class
    var getClass = function (a, d) {
        let required = "\n    required init() {}"
        return "class " + a + ": HandyJSON {\n" + d + required + "\n}"
    };

    // 生成變數
    var getVar = function (a, d) {
        return "    var " + d + ": " + a + "\n"
    };

    // swift  解析 json
    var generateSwift = function (a, d) {
        var c = "";
        if (q(a)) {
            if (a.length > 0) {
                for (var e = a[0], f = a.length - 1; 0 <= f; f--) {
                    var b = a[f];
                    q(b) ? b.length > e.length && (e = b) :
                        r(b) && Object.keys(b).length > Object.keys(e).length && (e = b)
                }
                c += generateSwift(e, d)
            }
        } else if (r(a)) for (e in a) {
            b = a[e];
            var h = toUpperVar(e);
            f = toLowerVar(e);
            if (q(b)) {
                var g;
                // 獲取第一個
                0 < b.length && (g = b[0]);

                if ("string" === typeof g) {
                    c += getVar("[String]!", f);
                } else {
                    if ("number" === typeof g) {
                        // 判斷浮點數
                        if (0 <= b.toString().indexOf(".")) {
                            c += getVar("[Float]!", f);
                        } else {
                            c += getVar("[Int]!", f);
                        }
                    } else if ("boolean" === typeof g) {
                        c += getVar("[Bool]", f)
                    } else if ("object" === typeof g) {
                        h += "Item";
                        c += getVar("[" + h + "]!", f);
                        b = generateSwift(b, e);
                        if (0 < k.length) {
                            k += "\r\n\r\n" + getClass(h, b)
                        } else {
                            k = getClass(h, b)
                        }
                    }
                }
            } else {
                if (r(b)) {
                    b = generateSwift(b, e)
                    c += getVar(h, f)
                    k = 0 < k.length ? k + "\r\n\r\n" + getClass(h, b) : getClass(h, b)
                } else {
                    if ("string" === typeof b) {
                        c += getVar("String = ''", f)
                    } else if ("number" === typeof b) {
                        // 判斷浮點數
                        if (0 <= b.toString().indexOf(".")) {
                            c += getVar("Float = 0.0", f)
                        } else {
                            c += getVar("Int = 0", f)
                        }
                    } else if ("boolean" === typeof b) {
                        c += getVar("Bool = false", f)
                    }
                }
            }
        } else alert("key = " + d); return c
    };

    var swiftFunc = function (a, d) {
        k = ""
        0 == d.length && (d = "DefaultModelName");
        var c = generateSwift(a, d);
        k = 0 < k.length ? k + "\r\n\r\n" + getClass(d, c) : getClass(d, c);
        return k
    };

    return {
        swiftModel: function () {
            var d = eval("(" + jsonString + ")");
            return swiftFunc(d, toUpperVar(className))
        }
    }

};

exports.generateCode = generateCode;
複製程式碼

如何呼叫?

var generateModel = require('./generateModel.js');
var fs = require("fs")
const { exec } = require('child_process');

var d = "{'error': 0,'msg': 'success','data': [{'id': 27,'name': '協議和幫助','sname': 'xy','parent_id': '0','flag': '0','created': '2017-01-15 09:47:09','tag':[1, 5], 'dated': '2017-01-15 16:31:32'}]}"

var fileName = "testModel"
var code = generateModel.generateCode(d, fileName).swiftModel();
console.log(code)


fs.writeFile('./Swift_Code/' + fileName + '.swift', code,  function(err) {
    if (err) {
        return console.error(err);
    }
 });
 
 // 格式化程式碼
 exec('swiftformat ./Swift_Code/' + fileName + '.swift --swiftversion 4.2 ', (err, stdout, stderr) => {
     if(err) {
         return;
     }
 })
 
複製程式碼

執行上述程式碼即可生成如下檔案:

class DataItem: HandyJSON {
    var id: Int = 0
    var name: String = ""
    var sname: String = ""
    var parent_id: String = ""
    var flag: String = ""
    var created: String = ""
    var tag: [Int]!
    var dated: String = ""

    required init() {}
}

class TestModel: HandyJSON {
    var error: Int = 0
    var msg: String = ""
    var data: [DataItem]!

    required init() {}
}

複製程式碼

這裡為了避免Optional解析發生Crash,所以都賦了一個預設值,總感覺會有一點問題,後面再修改。。。

將JavaScript解析Json程式碼翻譯成Swift

完成了Model的生成,將JavaScript的解析Json程式碼解析翻譯成Swift就簡單很多了

jsonObj.data[0].name 甚至可以不用修改直接翻譯即可 ~

最後貼上生成HandyJson的 程式碼

如何將JavaScript轉化成Swift?(一)

如何將JavaScript轉化成Swift?(二)

相關文章