如何將JavaScript轉化成Swift?(三)
本文銜接如何將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 = "\nrequired 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,所以都賦了一個預設值,總感覺會有一點問題,後面再修改。。。