1. 程式人生 > >2018年最全網易微專業Java開發:聚焦Java開發工程師必知必會的知識技能

2018年最全網易微專業Java開發:聚焦Java開發工程師必知必會的知識技能

Object轉JsonString
如何使用: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、然後繼續下一次迴圈。。

閱讀更多
--------------------- 
作者:LJHSkyWalker 
來源:CSDN 
原文:https://blog.csdn.net/qq_31615049/article/details/85013129 
版權宣告:本文為博主原創文章,轉載請附上博文連結!