前言
关于Fastjson的相关知识可以查看我的这篇博客:史上最全的JSON解析之Fastjson,而关于手写简易版Fastjson有什么用呢?其实如果在实际使用的过程中还是推荐使用阿里巴巴官方的Fastjson,毕竟有人都帮你写好了直接用就可以了,而且自己写的一般是没有阿里写的运行快啦。手写简易版Fastjson只是为了锻炼思维以及复习Java反射知识罢了。话不多说,为了节省大家的时间,下面直接进入编码过程。
编码实现
必要的解释都在代码的注释里
Java对象
事先准备好一个用于转换成JSON字符串的Java对象:
/**
* @author guqueyue
* @Date 2020/5/28
* 人类
**/
// lombok插件的注解
@Data // getter、setter以及toString方法
@AllArgsConstructor // 全参构造方法
@NoArgsConstructor // 无参构造方法
@Accessors(chain = true) // 开启链式编程
public class Person {
/**
* 姓名
*/
private String name;
/**
* 性别
*/
private String sex;
/**
* 年龄
*/
private Integer age;
}
核心代码
模拟Fastjson中toJsonString()
方法的核心代码:
/**
* @author guqueyue
* @Date 2020/5/28
* 我自己的FastJson
**/
public class MyJson {
/**
* 将任意对象转换为JSON字符串
* @param object
* @return
*/
public static final String toJsonString(Object object) throws IllegalAccessException {
// 获取反射对象
Class<?> clazz = object.getClass();
// 获取反射对象的所有属性,包括私有属性
Field[] fields = clazz.getDeclaredFields();
// 创建字符串类,便于拼接出JSON字符串
StringBuffer stringBuffer = new StringBuffer();
String str = "";
stringBuffer.append("{");
// 遍历所有属性
for (Field field : fields) {
// 第一次无须拼接逗号
if (stringBuffer.length() != 1) {
stringBuffer.append(",");
}
// 给私有属性授权,以便能够对于私有属性操作
field.setAccessible(true);
stringBuffer.append("\"");
stringBuffer.append(field.getName());
stringBuffer.append("\"");
stringBuffer.append(":");
// 两种判断属性值是否为字符串类型的方式
Boolean flag = field.getType().isInstance(str);
// Boolean flag = field.getType().toString().equals("class java.lang.String");
if (flag) { // 如果属性的类型为字符串,则给属性值加上双引号
stringBuffer.append("\"");
stringBuffer.append(field.get(object));
stringBuffer.append("\"");
} else {
stringBuffer.append(field.get(object));
}
}
stringBuffer.append("}");
return stringBuffer.toString();
}
}
实现效果
让我们来测试一下,看一下效果:
/**
* @author guqueyue
* @Date 2020/5/28
**/
public class FastJsonTest {
public static void main(String[] args) throws IllegalAccessException {
// 创建需要转换的对象
Person person = new Person()
.setName("小明")
.setSex("男")
.setAge(17);
// 将对象转换为Json字符串
String jsonString = MyJson.toJsonString(person);
// 打印到控制台
System.out.println(jsonString);
}
}
运行程序,控制台打印为:
转换成功!
答疑解惑
这个时候可能有小伙伴会问了:感觉你这个好麻烦呀,我不用反射不是也可以吗?如下所示:
/**
* @author guqueyue
* @Date 2020/5/28
* 不用反射将Java对象转换成JSON字符串
**/
public class MyTest {
public static void main(String[] args) {
// 创建需要转换的对象
Person person = new Person()
.setName("小明")
.setSex("男")
.setAge(17);
// 将对象转换为Json字符串
String jsonString = myJsonString(person);
// 打印到控制台
System.out.println(jsonString);
}
private static String myJsonString(Person person) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("{\"name\":\"");
stringBuffer.append(person.getName() + "\",\"sex\":\"");
stringBuffer.append(person.getSex() + "\",\"age\":");
stringBuffer.append(person.getAge() + "}");
return stringBuffer.toString();
}
}
运行效果为:
这样看来似乎不用反射不但更加简单,而且实现效果也相同。那为什么连阿里巴巴研发的Fastjson内部也是用反射写的?难道阿里巴巴的人故意把简单的问题复杂化是在炫技吗?当然不是,因为不用重复造轮子的终极奥义就在于:虽然造轮子的过程可能比较复杂,但我只需要编写一次,之后无论是什么对象我就可以直接使用。
而第二种方式看起来虽然简单,但是每一次转换不同的Java对象成JSON字符串就要重新编写代码。又或者,难不成你要写一堆if-else
判断穷尽世界上所有的Java对象,然后事先编写好所有的代码吗?