接下来,我们来编写序列化类 JsonSerializer,内容如下:
public class JsonSerializer {public static String serialize(Object object) throws IllegalAccessException {
Class<?> objectClass = object.getClass();
Map<String, String> jsonElements = new HashMap<>();
for (Field field : objectClass.getDeclaredFields()) {
field.setAccessible(true);
if (field.isAnnotationPresent(JsonField.class)) {
jsonElements.put(getSerializedKey(field), (String) field.get(object));
}
}
return toJsonString(jsonElements);
}
private static String getSerializedKey(Field field) {
String annotationValue = field.getAnnotation(JsonField.class).value();
if (annotationValue.isEmpty()) {
return field.getName();
} else {
return annotationValue;
}
}
private static String toJsonString(Map<String, String> jsonMap) {
String elementsString = jsonMap.entrySet()
.stream()
.map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"")
.collect(Collectors.joining(","));
return "{" + elementsString + "}";
}
}
JsonSerializer 类的内容看起来似乎有点多,但不要怕,我一点点来解释,直到你搞明白为止。
1)serialize() 方法是用来序列化对象的,它接收一个 Object 类型的参数。objectClass.getDeclaredFields() 通过反射的方式获取对象声明的所有字段,然后进行 for 循环遍历。在 for 循环中,先通过 field.setAccessible(true) 将反射对象的可访问性设置为 true,供序列化使用(如果没有这个步骤的话,private 字段是无法获取的,会抛出 IllegalAccessException 异常);再通过 isAnnotationPresent() 判断字段是否装饰了 JsonField 注解,如果是的话,调用 getSerializedKey() 方法,以及获取该对象上由此字段表示的值,并放入 jsonElements 中。
2)getSerializedKey() 方法用来获取字段上注解的值,如果注解的值是空的,则返回字段名。
3)toJsonString() 方法借助 Stream 流的方式返回格式化后的 JSON 字符串。如果对 Stream 流比较陌生的话,请查阅我之前写的 Stream 流入门。
看完我的解释,是不是豁然开朗了?
接下来,我们来写一个测试类 JsonFieldTest,内容如下:
public class JsonFieldTest {public static void main(String[] args) throws IllegalAccessException {
Writer cmower = new Writer(18,"沉默王二","Web全栈开发进阶之路");
System.out.println(JsonSerializer.serialize(cmower));
}
}
程序输出结果如下:
{"bookName":"Web全栈开发进阶之路","writerName":"沉默王二"}从结果上来看:
1)Writer 类的 age 字段没有装饰 @JsonField 注解,所以没有序列化。
2)Writer 类的 name 字段装饰了 @JsonField 注解,并且显示指定了字符串“writerName”,所以序列化后变成了 writerName。
3)Writer 类的 bookName 字段装饰了 @JsonField 注解,但没有显式指定值,所以序列化后仍然是 bookName。