如何使用:JSON.toJSONString(obj);
处理逻辑:JSON类是一个抽象类,实现了其中一个名为JSONAware的接口,这个接口中只有一个方法就是String toJSONString(),如下图所示:
该方法的实现逻辑是:
public String toJSONString() {
SerializeWriter out = new SerializeWriter();
try {
new JSONSerializer(out).write(this);
return out.toString();
} finally {
out.close();
}
}
SerializeWriter是Writer的子类,Writer是io包中的一个写字符流的抽象类,暂且不管。
new JSONSerializer,这里new的是一个
public JSONSerializer(SerializeWriter out){
this(out, SerializeConfig.getGlobalInstance());
}
public JSONSerializer(SerializeWriter out, SerializeConfig config){
this.out = out;
this.config = config;
}
接下来就要开始执行write操作,代码如下图所示,这里的object就是我们输入的待转变的内容,它可能是一个VO,是一个List,或者是个Map。
首先进行判空操作,
其次获取object的对象类型clazz,通过getObjectWriter工厂方法获取对应的(ObjectSerializer)writer,内部实现类似于HashMap的get,事实上类型和writer的映射关系存储在IdentityHashMap类中,详情自行查看SerializeConfig的SerializeConfig(int tableSize, boolean fieldBase)方法。例如List的ObjectSerializer是ListSerializer
接下来执行获取的具体对象类型的(ObjectSerializer)writer的write方法。
public final SerializeWriter out;
....
public final void write(Object object) {
if (object == null) {
out.writeNull();
return;
}
Class> clazz = object.getClass();
ObjectSerializer writer = getObjectWriter(clazz);
try {
writer.write(this, object, null, null, 0);
} catch (IOException e) {
throw new JSONException(e.getMessage(), e);
}
}
最后简述一下write的方法如何实现的。以ListSerializer的write为例:
假设我们的VO是如下定义的:
static class Person{
private int id;
private String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override
public String toString() {
return "Person{" + "id=" + id + ", name='" + name + '\'' + '}';
}
}
1、ListSerializer关键起点:
out.append('[');
for (int i = 0, size = list.size(); i < size; ++i) {
...
}
out.append(']');
2、首先创建对象createJavaBeanSerializer,
public final ObjectSerializer createJavaBeanSerializer(Class> clazz) {
SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy, fieldBased);
if (beanInfo.fields.length == 0 && Iterable.class.isAssignableFrom(clazz)) {
return MiscCodec.instance;
}
return createJavaBeanSerializer(beanInfo);
}
3、上述代码的TypeUtils.buildBeanInfo方法中存在下面代码中所列出的关键方法,就是根据反射获取所有的字段
public static void parserAllFieldToCache(Class> clazz,Map**fieldName*/String , Field> fieldCacheMap){
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String fieldName = field.getName();
if (!fieldCacheMap.containsKey(fieldName)) {
fieldCacheMap.put(fieldName, field);
}
}
if (clazz.getSuperclass() != null && clazz.getSuperclass() != Object.class) {
parserAllFieldToCache(clazz.getSuperclass(), fieldCacheMap);
}
}
在这一步,还要再按照getName,getId等bean的方法去获取bean的存在get方法的成员变量名,具体获取方式就是按照get3个字后面的大写字母匹配。
if(methodName.startsWith("get")){
if(methodName.length() < 4){
continue;
}
if(methodName.equals("getClass")){
continue;
}
if(methodName.equals("getDeclaringClass") && clazz.isEnum()){
continue;
}
char c3 = methodName.charAt(3);
String propertyName;
if(Character.isUpperCase(c3) //
|| c3 > 512 // for unicode method name
){
if(compatibleWithJavaBean){
propertyName = decapitalize(methodName.substring(3));
} else{
propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
}
propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName, 3);
} else if(c3 == '_'){
propertyName = methodName.substring(4);
} else if(c3 == 'f'){
propertyName = methodName.substring(3);
} else if(methodName.length() >= 5 && Character.isUpperCase(methodName.charAt(4))){
propertyName = decapitalize(methodName.substring(3));
} else{
continue;
}
boolean ignore = isJSONTypeIgnore(clazz, propertyName);
if(ignore){
continue;
}
//假如bean的field很多的情况一下,轮询时将大大降低效率
Field field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap);
if(field == null && propertyName.length() > 1){
char ch = propertyName.charAt(1);
if(ch >= 'A' && ch <= 'Z'){
String javaBeanCompatiblePropertyName = decapitalize(methodName.substring(3));
field = ParserConfig.getFieldFromCache(javaBeanCompatiblePropertyName, fieldCacheMap);
}
}
JSONField fieldAnnotation = null;
if(field != null){
fieldAnnotation = field.getAnnotation(JSONField.class);
if(fieldAnnotation != null){
if(!fieldAnnotation.serialize()){
continue;
}
ordinal = fieldAnnotation.ordinal();
serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
parserFeatures = Feature.of(fieldAnnotation.parseFeatures());
if(fieldAnnotation.name().length() != 0){
propertyName = fieldAnnotation.name();
if(aliasMap != null){
propertyName = aliasMap.get(propertyName);
if(propertyName == null){
continue;
}
}
}
if(fieldAnnotation.label().length() != 0){
label = fieldAnnotation.label();
}
}
}
if(aliasMap != null){
propertyName = aliasMap.get(propertyName);
if(propertyName == null){
continue;
}
}
if(propertyNamingStrategy != null){
propertyName = propertyNamingStrategy.translate(propertyName);
}
FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, parserFeatures,
annotation, fieldAnnotation, label);
fieldInfoMap.put(propertyName, fieldInfo);
}
4、根据字段生成json格式的字符
final char startSeperator = writeAsArray ? '[' : '{';
final char endSeperator = writeAsArray ? ']' : '}';
if (!unwrapped) {
out.append(startSeperator);
}
...
if (!unwrapped) {
out.append(endSeperator);
}
protected char[] genFieldNameChars() {
int nameLen = this.name.length();
char[] name_chars = new char[nameLen + 3];
this.name.getChars(0, this.name.length(), name_chars, 1);
name_chars[0] = '"';
name_chars[nameLen + 1] = '"';
name_chars[nameLen + 2] = ':';
return name_chars;
}
在out中write字段
if (!fieldInfo.unwrapped) {
if (directWritePrefix) {
out.write(fieldInfo.name_chars, 0, fieldInfo.name_chars.length);
} else {
fieldSerializer.writePrefix(serializer);
}
}
可以看出生成了字符数组:{"name":}
4、接下来按照VO的数据类型再用工厂生成ObjectSerializer,继续解析拼接字符串。如果获取的是int类型的数据,则创建IntegerCodec实例,调用他的write方法:
public class IntegerCodec implements ObjectSerializer, ObjectDeserializer {
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
SerializeWriter out = serializer.out;
Number value = (Number) object;
if (value == null) {
out.writeNull(SerializerFeature.WriteNullNumberAsZero);
return;
}
if (object instanceof Long) {
out.writeLong(value.longValue());
} else {
out.writeInt(value.intValue());
}
if (out.isEnabled(SerializerFeature.WriteClassName)) {
Class> clazz = value.getClass();
if (clazz == Byte.class) {
out.write('B');
} else if (clazz == Short.class) {
out.write('S');
}
}
}
5、生成value以后接下来生成下一个字段的value,在两个字段的value之间是","
在javaBeanSerializer里的代码片段
if (commaFlag) {
if (fieldInfo.unwrapped
&& propertyValue instanceof Map
&& ((Map) propertyValue).size() == 0) {
continue;
}
out.write(',');
if (out.isEnabled(SerializerFeature.PrettyFormat)) {
serializer.println();
}
6、当List中一个对象的所有字段全都write后,最后调用out.appent添加结束大括号
if (!unwrapped) {
out.append(endSeperator);
}
7、然后继续下一次循环。。