最近为了加速开发速度,写了不少半成品的框架。包括在Android上实现了一个简单的SpringMVC,这个可以看我前面的文章,其中一个模块就是JSON的ORM解析。
实现如下的注解关系映射
@JsonOrm
public class UserInfoModel implements IHandler{
@BindTextView(R.id.text1)
@JsonString
private String name;
@BindTextView(R.id.text3)
@JsonString
private String pass;
@BindRecycleView(R.id.list)
@BindObj
@JsonSet(clazz = ItemModel.class)
private List<ItemModel> obj;
@Override
public void handler() {
name = name+"handled";
}
}
1.首先分析JSON的数据结构
毫无疑问,JSON是一个树形结构
简单的JSON树
那么,对于树形结构我们将使用递归去遍历。
很显然我们需要根据我们的数据模型类和其上的注解构建一个树形结构,然后根据这个树形结构解析每次过来的JSON数据实例。
2.构建JSON树形结构
单个叶子节点数据结构
public class JsonMem {
//json中对应的key
private String key;
//json元素类型,普通元素,JSONObject,JSONArrary,或者根结点
private JsonObjType jsontype;
//对应数据模型model中的类型
private Class type;
//对应数据模型model中的field
private Field field;
//子节点列表
private List<JsonMem> childs;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Class getType() {
return type;
}
public void setType(Class type) {
this.type = type;
}
public Field getField() {
return field;
}
public void setField(Field field) {
this.field = field;
}
public List<JsonMem> getChilds() {
return childs;
}
public void setChilds(List<JsonMem> childs) {
this.childs = childs;
}
public JsonObjType getJsontype() {
return jsontype;
}
public void setJsontype(JsonObjType jsontype) {
this.jsontype = jsontype;
}
}
public enum JsonObjType {
HEAD,
OBJECT,
ARRAY,
ELEMENT
}
开始通过解析Model类构建JSON树
public class JsonParse {
public static JsonTree establish(Class clazz){
JsonMem headmem = new JsonMem();
headmem.setJsontype(JsonObjType.HEAD);
headmem.setType(clazz);
headmem.setKey(clazz.getName());
//开始递归建立树
establish(headmem);
JsonTree jsonTree = new JsonTree();
jsonTree.setTop(headmem);
return jsonTree;
}
private static void establish(JsonMem mem){
Field[] fields = mem.getType().getDeclaredFields();
List<JsonMem> childs = new ArrayList<>();
//遍历所有域
for (Field field:fields){
Annotation[] annotations = field.getAnnotations();
if (annotations == null||annotations.length == 0)
continue;
field.setAccessible(true);
//便利所有注解
for (Annotation annotation:annotations){
Class<? extends Annotation> type = annotation.annotationType();
//如果元素是JSONArray
if (type == JsonSet.class){
JsonSet set = (JsonSet) annotation;
String key = set.name();
if (key.equals(""))
key = field.getName();
JsonMem jsonMem = new JsonMem();
jsonMem.setKey(key);
jsonMem.setJsontype(JsonObjType.ARRAY);
jsonMem.setField(field);
jsonMem.setType(set.clazz());
//判断JSONArray的item是否是普通元素还是JSONObject,这里普通元素暂时偷懒用String代替
//如果不是普通类型则需要递归解析
if (jsonMem.getType()!=String.class)
establish(jsonMem);
childs.add(jsonMem);
//如果元素是JsonObject
}else if (type == JsonObject.class){
JsonObject jsonObject = (JsonObject) annotation;
String key = jsonObject.value();
if (key.equals(""))
key = field.getName();
JsonMem jsonMem = new JsonMem();
jsonMem.setKey(key);
jsonMem.setJsontype(JsonObjType.OBJECT);
jsonMem.setField(field);
jsonMem.setType(field.getType());
//递归解析
establish(jsonMem);
childs.add(jsonMem);
}else{
//只是普通元素
JsonBase jbase = annotation.annotationType().getAnnotation(JsonBase.class);
if (jbase == null)
continue;
String key = getItem(annotation);
if (key == null||key.equals(""))
key = field.getName();
Class valueType = jbase.value();
JsonMem jsonMem = new JsonMem();
jsonMem.setKey(key);
jsonMem.setJsontype(JsonObjType.ELEMENT);
jsonMem.setField(field);
jsonMem.setType(field.getType());
childs.add(jsonMem);
}
}
}
if (childs.size()!=0)
mem.setChilds(childs);
}
现在我们拿到了JsonTree对象。存储了JSON的结构和元素对应Model的关系,以及相关的反射类型。这样当json数据来的时候,我们只需要遍历这个JsonTree,然后对照其结构依次取出json里的内容即可。
3.解析json字符串实例
public static <T> T getValue(JsonTree tree,String json) throws Exception{
Class clazz = tree.getTop().getType();
T t = null;
//反射生成一个Model对象
t = (T) clazz.newInstance();
//取出根结点开始遍历解析
getValue(tree.getTop(),json,t);
return t;
}
private static void getValue(JsonMem mem,String json,Object object) throws Exception {
Field field = mem.getField();
Class type = mem.getType();
List<JsonMem> childs = mem.getChilds();
//依旧是判断元素类型
switch (mem.getJsontype()){
//如果是根节点
case HEAD:
JSONObject headobj = new JSONObject(json);
if (childs!=null){
//遍历子元素
for (JsonMem child:childs){
String str = headobj.getString(child.getKey());
getValue(child,str,object);
}
}
break;
case ELEMENT:
//普通元素直接赋值
field.set(object,json);
break;
//JSONObject需要递归其子元素
case OBJECT:
JSONObject jsonObject = new JSONObject(json);
Object valueobj = type.newInstance();
if (childs!=null){
for (JsonMem child:childs){
String str = jsonObject.getString(child.getKey());
getValue(child,str,valueobj);
}
}
field.set(object,valueobj);
break;
//如果是JSONArrary
case ARRAY:
JSONArray array = new JSONArray(json);
if (array == null||array.length() == 0)
break;
List list = new ArrayList();
//如果item是普通元素则直接赋值
if (type == String.class){
for (int i = 0;i < array.length();i++){
list.add(array.getString(i));
}
}else {
//否则递归
for (int i = 0;i < array.length();i++){
Object arritem = type.newInstance();
JSONObject subobj = array.getJSONObject(i);
if (childs!=null){
for (JsonMem child:childs){
String str = subobj.getString(child.getKey());
getValue(child,str,arritem);
}
}
list.add(arritem);
}
}
field.set(object,list);
break;
}
}
总的来说还是个半成品,但是基本结构已经实现,勉强也能用吧,现在还不支持json数组直接嵌套,个人比较懒。