的這幾天公司項(xiàng)目在重構(gòu),以前Api的返回?cái)?shù)據(jù)的數(shù)據(jù)模型是根據(jù)文檔用GsonFormat自動(dòng)生成的,方便是方便慢逾,但是有很多其實(shí)是同一個(gè)數(shù)據(jù)模型,但是自動(dòng)生成的工具無(wú)法識(shí)別灭红,最終導(dǎo)致我們的模型非常亂侣滩,有很多重復(fù)的Model類(lèi)。
最后我們后端程序是Java寫(xiě)的变擒,他們的數(shù)據(jù)模型其實(shí)丟給我們就能用君珠,所以這次重構(gòu)的時(shí)候就把數(shù)據(jù)模型和后端保持一致了,這就產(chǎn)生了一個(gè)問(wèn)題娇斑,iOS的同學(xué)用的OC策添,還是要手寫(xiě)材部,重構(gòu)代碼 幾百個(gè)model類(lèi),想想就憂(yōu)傷啊唯竹。
所以為了建立我們Android開(kāi)發(fā)同學(xué)和iOS開(kāi)發(fā)同學(xué)的友誼乐导,我們決定用java的類(lèi)為我們iOS的同學(xué)生成他們要的模型。Let go摩窃!
思路
最早是打算直接處理java文件兽叮,把java文件當(dāng)成文本文件,提取里面的字段信息猾愿,用正則表達(dá)式之類(lèi)的提取類(lèi)的元信息字段信息等鹦聪,然后拼成字符串寫(xiě)入到文件里,實(shí)驗(yàn)之后覺(jué)得太麻煩了蒂秘,于是放棄了泽本。
中途也嘗試了一下google的開(kāi)源庫(kù)j2objc,試用之后發(fā)現(xiàn)生成的代碼基本不是給人看的,很多無(wú)關(guān)的信息姻僧,因?yàn)樗饕窍M鸒C能直接調(diào)用java的代碼规丽,不需要人去修改,庫(kù)很完整功能很強(qiáng)大撇贺,但是對(duì)于我的需求來(lái)說(shuō)太過(guò)頭了赌莺,我只希望簡(jiǎn)單的生成一下OC的模型而已。后來(lái)想到就在項(xiàng)目里松嘶,把類(lèi)加載后艘狭,再利用java reflect拿到類(lèi)的所有字段然后改裝成OC的語(yǔ)法寫(xiě)入到文件即可,項(xiàng)目很簡(jiǎn)單翠订,測(cè)試之后基本可用巢音。
部分代碼
下面是解析java模型中數(shù)據(jù)的類(lèi)型,并且對(duì)應(yīng)到oc當(dāng)中的類(lèi)型尽超,可以根據(jù)自己的需求進(jìn)行修改官撼,比如我把double、float似谁、long都是用oc的CGFloat處理了傲绣。
/**
* 解析type的信息并存儲(chǔ)在map中,方便后面寫(xiě)入到oc文件
*
* @param type
* @param container
* @param fieldName
* @return
*/
private void saveTypeToMap(Class type, Map<String, String> container,
String fieldName, List<String> otherTypeList) {
String ocType;
//判斷java類(lèi)的類(lèi)型巩踏,并且對(duì)應(yīng)到oc的類(lèi)型
if (type == int.class || type == Integer.class) {
ocType = "NSInteger";
} else if (type == long.class || type == Long.class) {
ocType = "CGFloat";
} else if (type == boolean.class || type == Boolean.class) {
ocType = "BOOL";
} else if (type == double.class || type == Double.class) {
ocType = "CGFloat";
} else if (type == float.class || type == Float.class || type == BigDecimal.class) {
ocType = "CGFloat";
} else if (type == String.class || type == Date.class || type.isEnum()) {
ocType = "NSString";
} else if (type == List.class) {
ocType = "NSArray";
} else if (type == Object.class) {
ocType = "NSDictionary";
} else {
//如果不是基礎(chǔ)類(lèi)型則為其他的自定義類(lèi)型
ocType = type.getName();
int index = ocType.lastIndexOf(".");
String typeName = classPrefix + ocType.substring(index + 1, ocType.length());
ocType = typeName;
if (!otherTypeList.contains(typeName)) {
otherTypeList.add(typeName);
}
}
//處理特殊字段斜筐,如果字段名稱(chēng)是id或者Category需要特殊處理 這里也可以根據(jù)自己的需要進(jìn)行特別的映射處理
if (fieldName.equals("id")) {
container.put("Id", ocType);
} else if (fieldName.equals("Category")) {
container.put("HDCategory", ocType);
} else if (fieldName.equals("Description")) {
container.put("HDDescription", ocType);
} else {
container.put(fieldName, ocType);
}
}
使用的時(shí)候把OCTranslator類(lèi)放倒自己的項(xiàng)目里任意位置,然后設(shè)置下下面的內(nèi)容蛀缝,指定一下java模型的包的路徑,然后運(yùn)行即可在項(xiàng)目根目錄生成一個(gè)目錄叫OCModelOutput的文件夾目代,里面就是生成好的OC模型了屈梁。
//OC模型的前綴
static String classPrefix = "GD";
//公司名稱(chēng) 會(huì)顯示到文件頭部的Copyright信息中
static String corporateName = "Shanghai HEADING Information Engineering Co., Ltd.";
//顯示到文件頭部到元信息中
static String schemeName = "TestProject";
//指定java模型包的路徑
static String[] modelDirectories = new String[]{
};
最后看看效果:
拋磚引玉嗤练,感興趣的同學(xué)可以試試,說(shuō)不定iOS開(kāi)發(fā)是個(gè)妹子在讶,這一步成功建立友誼之后煞抬,接下來(lái)怎么發(fā)展就看你啦。
項(xiàng)目代碼和demo在這里:
https://github.com/lazydeer/J2OCModel
有需要的朋友快動(dòng)手試試吧构哺。