Simplify-Core -- java对象转换成Json(Json generator)
来源:互联网 发布:刘慈欣 知乎 编辑:程序博客网 时间:2024/06/05 20:55
先感叹一波今天正式毕业,拿到了毕业证和学位证,然后博客也有三个多月没写了,最近自己写了一个工具类的项目,Simplify,旨在简化重复的JAVA代码,基于JDK8,无其它jar包依赖,提供序列化,json,日期等常见操作。json generator部分写的比较完善了, parse部分能跑简单的测试用例。
网上json的工具类数不胜数,自己写主要还是实现最基本的json功能满足大部分的需要,更重要是锻炼编码水平。Simplify里的json测试用例都以fastjson为标准,实现原理也借鉴了fastjson,但是水平有限,能看懂别人的代码才能借鉴,大部分没看懂只能自己琢磨了。这里先写generator部分的实现原理。分享给大家。
项目地址:https://github.com/lovejj1994/Simplify-Core
欢迎路过的大牛对项目提出建议。
整个Json框架需要做哪些准备?
1.需要一个公开的入口,让使用者简单的调用静态方法就可以实现java对象转换为json格式的字符串。
2.再往深一层,对于一个java对象,里面有许多成员变量,变量有不同的类型,对于不同的类型对象,需要有不同的处理方法,所以不同的类型要有专门的“处理器”(codec),为了规范这些“处理器”,需要设计一个接口(IJson),定义专门的方法(Object writeJsonString(Object o))返回处理后的字符串。
3.整个流程中,反射充当访问对象的重要途径,对于一个对象中的不同成员变量,要定义一个规则:只能通过公有(public)的get,set方法才能访问到这个变量,虽然反射可以暴力访问,但是对于用户来说,写私有的,或者不符合编码规范(不是驼峰式)的get,set方法的成员变量,用户并不想你去访问它并且转换为json格式。
具体设计
1.创建一个Json类,里面有一个toJsonString()方法,这是唯一给用户使用的入口。
Json.javaprivate static JsonSerializer jsonSerializer;public static String toJsonString(Object t) { if (Objects.isNull(t)) { return null; } jsonSerializer = JsonSerializer.getInstance(); return jsonSerializer.convertToJsonString(t);}
- JsonSerializer 是专门负责 调度Json generator 的各种方法,java对象转json格式字符串 都由它负责。
AbstractJson 是一个抽象类,负责存放一些公共方法,在convertToJsonString方法中,有一个getSuitableHandler()方法,它就定义在AbstractJson 中,它的责任在于根据传进去的object找到合适的codec。
public class JsonSerializer extends AbstractJson { private static Logger logger = Logger.getLogger(JsonSerializer.class.getName()); private static JsonSerializer jsonSerializer = new JsonSerializer(); private JsonSerializer() { } public static JsonSerializer getInstance() { return jsonSerializer; } //getSuitableHandler public String convertToJsonString(Object o) { Class<?> c = o.getClass(); IJson suitableHandler = getSuitableHandler(c); return (String) suitableHandler.writeJsonString(o); }}
getSuitableHandler方法检测传进去的class类型,然后返回合适的codec。
protected IJson getSuitableHandler(Class c) { if (Collection.class.isAssignableFrom(c)) { c = Collection.class; } if (Map.class.isAssignableFrom(c)) { c = Map.class; } if (Number.class.isAssignableFrom(c)) { c = Number.class; } if (c.isArray()) { return new ArrayCodec(); } switch (c.getTypeName()) { case Const.NUMBER_TYPE: return new NumberCodec(); case Const.COLLECTION_TYPE: return new CollectionCodec(); case Const.MAP_TYPE: return new MapCodec(); case Const.STRING_TYPE: return new StringCodec(); case Const.BOOLEAN_TYPE: return new BooleanCodec(); case Const.CHAR_TYPE: return new CharCodec(); case Const.DATE_TYPE: return new DateCodec(); case Const.LOCALDATE_TYPE: return new LocalDateCodec(); case Const.LOCALDATETIME_TYPE: return new LocalDateTimeCodec(); case Const.LOCALTIME_TYPE: return new LocalTimeCodec(); default: return new ObjectCodec(); } }
部分codec展示:
/** * Char 解析器 * Created by panqian on 2017/6/6. */public class LongCodec extends AbstractJson implements IJson { StringBuffer sb; @Override public Object writeJsonString(Object o) { Long l = (Long) o; sb = new StringBuffer(1); numberHandle(sb, l); return sb.toString(); } @Override public Object parse(Object o, Method m) { if (Objects.isNull(o)) { return null; } BigInteger bi = new BigInteger(o + ""); return bi.longValue(); }}/** * Number 解析器 * Created by panqian on 2017/6/6. */public class NumberCodec extends AbstractJson implements IJson { StringBuffer sb; @Override public Object writeJsonString(Object o) { Number n = (Number) o; sb = new StringBuffer(n.toString().length()); numberHandle(sb, n); return sb.toString(); } @Override public Object parse(Object o, Method m) { BigDecimal bd = (BigDecimal) o; return bd.doubleValue(); }}
codec实现IJson接口, 规定好了codec的规范,writeJsonString用于 转换Json,parse用于解析json。
** * Created by panqian on 2017/6/6. */public interface IJson extends Serializable { Object writeJsonString(Object o); Object parse(Object o, Method m);}
3.简单的基本类型可以直接找到合适的 codec,对于自定义类型,需要用ObjectCodec进行成员变量分解,每个成员变量重新找自己合适的codec,然后执行writeJsonString返回合格的json格式,对于object的分解是一种递归调用。
object分解递归代码,特别注意serializerObject方法。
/** * Object 解析器 * Created by panqian on 2017/6/8. */public class ObjectCodec extends AbstractJson implements IJson { private static Logger logger = Logger.getLogger(JsonSerializer.class.getName()); StringJoiner sj; private String serializerObject(Object o) { sj = new StringJoiner(Const.COMMA, Const.PRE_BRACE, Const.POST_BRACE); Class<?> cClass = o.getClass(); //查找该类所有声明的方法(除Object) List<Method> allDeclaredMethods = ReflectionUtils.getAllDeclaredMethods(cClass); //筛选public get方法 ArrayList<Method> publicGetMethods = new ArrayList<>(); if (null != allDeclaredMethods && allDeclaredMethods.size() > 0) { for (Method m : allDeclaredMethods) { String modifier = ReflectionUtils.getModifier(m); if (modifier.contains(Const.PUBLIC) && m.getName().contains(Const.GET)) { publicGetMethods.add(m); } } } if (null != publicGetMethods && publicGetMethods.size() > 0) { Collections.sort(publicGetMethods, (x, y) -> Collator.getInstance().compare(x.getName(), y.getName())); for (Method method : publicGetMethods) { String name = method.getName(); String substring = name.substring(3, name.length()); char c = substring.charAt(0); if (c >= 'A' && c <= 'Z') { Character b = (char) (c + 32); String key = b.toString().concat(substring.substring(1, substring.length())); try { Object invoke = method.invoke(o); if (Objects.nonNull(invoke)) { sj.add(Const.SINGLE_QUOTES + key + Const.SINGLE_QUOTES + Const.COLON + JsonSerializer.getInstance().convertToJsonString(invoke)); } } catch (IllegalAccessException e) { logger.severe(e.getMessage()); } catch (InvocationTargetException e) { logger.severe(e.getMessage()); } } } } return sj.toString(); } @Override public Object writeJsonString(Object o) { String result = serializerObject(o); return result; } @Override public Object parse(Object o, Method m) { JsonObject jo = (JsonObject) o; Type[] genericParameterTypes = m.getGenericParameterTypes(); Type t = null; for (Type type : genericParameterTypes) { if (ParameterizedType.class.isAssignableFrom(type.getClass())) { for (Type t1 : ((ParameterizedType) type).getActualTypeArguments()) { t = t1; } } } try { Class<?> aClass = Class.forName(t.getTypeName()); Object o1 = aClass.newInstance(); //查找该类所有声明的方法(除Object) List<Method> allDeclaredMethods = ReflectionUtils.getAllDeclaredMethods(aClass); //筛选public set方法 ArrayList<Method> publicSetMethods = new ArrayList<>(); if (null != allDeclaredMethods && allDeclaredMethods.size() > 0) { for (Method md : allDeclaredMethods) { String modifier = ReflectionUtils.getModifier(md); if (modifier.contains(Const.PUBLIC) && md.getName().startsWith(Const.SET)) { publicSetMethods.add(md); } } } if (null != publicSetMethods && publicSetMethods.size() > 0) { for (Method md : publicSetMethods) { String methodName = md.getName(); String variable = methodName.substring(3, methodName.length()); Class<?>[] parameterTypes = md.getParameterTypes(); Class parameterType = null; if (null != parameterTypes && parameterTypes.length == 1) { parameterType = parameterTypes[0]; } variable = variable.substring(0, 1).toLowerCase() + variable.substring(1, variable.length()); if (jo.containsKey(variable)) { Object oo = jo.get(variable); IJson suitableHandler = getSuitableParseHandler(parameterType); Object parse = suitableHandler.parse(oo, md); try { md.invoke(o1, parse); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } } return o1; } catch (ClassNotFoundException e) { } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } return null; }}
上面是大致的Json generate 流程,使用规则 项目里有完整的测试用例。
- Simplify-Core -- java对象转换成Json(Json generator)
- Simplify-Core --Json解析(Json parser)
- java json字符串转换成json对象
- json转换成Java对象
- java对象转换成json
- 将Java对象转换成JSON对象
- 使用json-lib将java对象转换成json字符串
- 使用json-lib jsonObject 把json 转换成 java对象
- java JSON学习—List集合转换成JSON对象
- [Json]java中List转换成json对象
- 对象转换成JSON
- Java对象 json之间的转换(json-lib)
- JSON --- JAVA对象转换为json
- 将JAVA对象转换成JSON字符串
- java对象转换成json数据
- 将JAVA对象转换成JSON字符串
- 将java对象转换成json字符串
- JSON 转换成Java对象的方法
- 使用qampp集成服务器配置虚拟域名解决无法加载控制器情况
- 用Javascript实现冒泡排序,二种方法的比较
- Git smartgit gitlab 合并的坑
- MxNet系列——Windows上安装MxNet
- 内存的五大分区详解
- Simplify-Core -- java对象转换成Json(Json generator)
- 自己的一些android面试经验
- springcloud config 访问配置文件
- 14_摄像头相关的
- Freemarker实例教程
- MIT提出Matlab插件mNeuron:实现深度模型神经元的可视化
- 结构体和联合体的区别
- JS 堆 栈 与 拷贝
- jsp详细介绍