本文銜接 如何將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的 程式碼