的这几天公司项目在重构,以前Api的返回数据的数据模型是根据文档用GsonFormat自动生成的,方便是方便,但是有很多其实是同一个数据模型,但是自动生成的工具无法识别,最终导致我们的模型非常乱,有很多重复的Model类。
最后我们后端程序是Java写的,他们的数据模型其实丢给我们就能用,所以这次重构的时候就把数据模型和后端保持一致了,这就产生了一个问题,iOS的同学用的OC,还是要手写,重构代码 几百个model类,想想就忧伤啊。
所以为了建立我们Android开发同学和iOS开发同学的友谊,我们决定用java的类为我们iOS的同学生成他们要的模型。Let go!
思路
最早是打算直接处理java文件,把java文件当成文本文件,提取里面的字段信息,用正则表达式之类的提取类的元信息字段信息等,然后拼成字符串写入到文件里,实验之后觉得太麻烦了,于是放弃了。
中途也尝试了一下google的开源库j2objc,试用之后发现生成的代码基本不是给人看的,很多无关的信息,因为它主要是希望OC能直接调用java的代码,不需要人去修改,库很完整功能很强大,但是对于我的需求来说太过头了,我只希望简单的生成一下OC的模型而已。后来想到就在项目里,把类加载后,再利用java reflect拿到类的所有字段然后改装成OC的语法写入到文件即可,项目很简单,测试之后基本可用。
部分代码
下面是解析java模型中数据的类型,并且对应到oc当中的类型,可以根据自己的需求进行修改,比如我把double、float、long都是用oc的CGFloat处理了。
/**
* 解析type的信息并存储在map中,方便后面写入到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类的类型,并且对应到oc的类型
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 {
//如果不是基础类型则为其他的自定义类型
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);
}
}
//处理特殊字段,如果字段名称是id或者Category需要特殊处理 这里也可以根据自己的需要进行特别的映射处理
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);
}
}
使用的时候把OCTranslator类放倒自己的项目里任意位置,然后设置下下面的内容,指定一下java模型的包的路径,然后运行即可在项目根目录生成一个目录叫OCModelOutput的文件夹,里面就是生成好的OC模型了。
//OC模型的前缀
static String classPrefix = "GD";
//公司名称 会显示到文件头部的Copyright信息中
static String corporateName = "Shanghai HEADING Information Engineering Co., Ltd.";
//显示到文件头部到元信息中
static String schemeName = "TestProject";
//指定java模型包的路径
static String[] modelDirectories = new String[]{
};
最后看看效果:
抛砖引玉,感兴趣的同学可以试试,说不定iOS开发是个妹子,这一步成功建立友谊之后,接下来怎么发展就看你啦。
项目代码和demo在这里:
https://github.com/lazydeer/J2OCModel
有需要的朋友快动手试试吧。