博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
fastjson深度源码解析- 序列化(三) - 序列化字段属性键值对
阅读量:4052 次
发布时间:2019-05-25

本文共 8162 字,大约阅读时间需要 27 分钟。

SerializeWriter成员函数

序列化字段名称

public void writeFieldName(String key, boolean checkSpecial) {        if (key == null) {            /** 如果字段key为null, 输出 "null:" */            write("null:");            return;        }        if (useSingleQuotes) {            if (quoteFieldNames) {                /** 使用单引号并且在字段后面加':'输出 标准的json key*/                writeStringWithSingleQuote(key);                write(':');            } else {                /** 输出key,如果有特殊字符会自动添加单引号 */                writeKeyWithSingleQuoteIfHasSpecial(key);            }        } else {            if (quoteFieldNames) {                /** 使用双引号输出json key 并添加 : */                writeStringWithDoubleQuote(key, ':');            } else {                boolean hashSpecial = key.length() == 0;                for (int i = 0; i < key.length(); ++i) {                    char ch = key.charAt(i);                    boolean special = (ch < 64 && (sepcialBits & (1L << ch)) != 0) || ch == '\\';                    if (special) {                        hashSpecial = true;                        break;                    }                }                if (hashSpecial) {                    /** 如果包含特殊字符,会进行特殊字符转换输出,eg: 使用转换后的native编码输出 */                    writeStringWithDoubleQuote(key, ':');                } else {                    /** 输出字段不加引号 */                    write(key);                    write(':');                }            }        }    }

序列化字段名称方法writeFieldName主要的任务:

  1. 完成字段特殊字符的转译
  2. 添加字段的引号

处理输出key的特殊字符方法writeStringWithDoubleQuote前面已经分析过了,序列化字段名称是否需要添加引号和特殊字符处理参考writeKeyWithSingleQuoteIfHasSpecial

private void writeKeyWithSingleQuoteIfHasSpecial(String text) {        final byte[] specicalFlags_singleQuotes = IOUtils.specicalFlags_singleQuotes;        int len = text.length();        int newcount = count + len + 1;        if (newcount > buf.length) {            if (writer != null) {                if (len == 0) {                    /** 如果字段为null, 输出空白字符('':)作为key */                    write('\'');                    write('\'');                    write(':');                    return;                }                boolean hasSpecial = false;                for (int i = 0; i < len; ++i) {                    char ch = text.charAt(i);                    if (ch < specicalFlags_singleQuotes.length && specicalFlags_singleQuotes[ch] != 0) {                        hasSpecial = true;                        break;                    }                }                /** 如果有特殊字符,给字段key添加单引号 */                if (hasSpecial) {                    write('\'');                }                for (int i = 0; i < len; ++i) {                    char ch = text.charAt(i);                    if (ch < specicalFlags_singleQuotes.length && specicalFlags_singleQuotes[ch] != 0) {                        /** 如果输出key中包含特殊字符,添加转译字符并将特殊字符替换成普通字符 */                        write('\\');                        write(replaceChars[(int) ch]);                    } else {                        write(ch);                    }                }                /** 如果有特殊字符,给字段key添加单引号 */                if (hasSpecial) {                    write('\'');                }                write(':');                return;            }            /** 输出器writer为null触发扩容,扩容到为原有buf容量1.5倍+1, copy原有buf的字符*/            expandCapacity(newcount);        }        if (len == 0) {            int newCount = count + 3;            if (newCount > buf.length) {                expandCapacity(count + 3);            }            buf[count++] = '\'';            buf[count++] = '\'';            buf[count++] = ':';            return;        }        int start = count;        int end = start + len;        /** buffer能够容纳字符串,直接拷贝text到buf缓冲数组 */        text.getChars(0, len, buf, start);        count = newcount;        boolean hasSpecial = false;        for (int i = start; i < end; ++i) {            char ch = buf[i];            if (ch < specicalFlags_singleQuotes.length && specicalFlags_singleQuotes[ch] != 0) {                if (!hasSpecial) {                    newcount += 3;                    if (newcount > buf.length) {                        expandCapacity(newcount);                    }                    count = newcount;                    /** 将字符后移两位,插入字符'\ 并替换特殊字符为普通字符 */                    System.arraycopy(buf, i + 1, buf, i + 3, end - i - 1);                    /** 将字符后移一位 */                    System.arraycopy(buf, 0, buf, 1, i);                    buf[start] = '\'';                    buf[++i] = '\\';                    buf[++i] = replaceChars[(int) ch];                    end += 2;                    buf[count - 2] = '\'';                    hasSpecial = true;                } else {                    newcount++;                    if (newcount > buf.length) {                        expandCapacity(newcount);                    }                    count = newcount;                    /** 包含特殊字符,将字符后移一位,插入转译字符\ 并替换特殊字符为普通字符 */                    System.arraycopy(buf, i + 1, buf, i + 2, end - i);                    buf[i] = '\\';                    buf[++i] = replaceChars[(int) ch];                    end++;                }            }        }        buf[newcount - 1] = ':';    }

序列化Boolean类型字段键值对

public void writeFieldValue(char seperator, String name, boolean value) {        if (!quoteFieldNames) {            /** 如果不需要输出双引号,则一次输出字段分隔符,字段名字,字段值 */            write(seperator);            writeFieldName(name);            write(value);            return;        }        /** true 占用4位, false 占用5位 */        int intSize = value ? 4 : 5;        int nameLen = name.length();        /** 输出总长度, 中间的4  代表 key 和 value 总共占用4个引号 */        int newcount = count + nameLen + 4 + intSize;        if (newcount > buf.length) {            if (writer != null) {                /** 依次输出字段分隔符,字段:字段值 */                write(seperator);                writeString(name);                write(':');                write(value);                return;            }            /** 输出器writer为null触发扩容,扩容到为原有buf容量1.5倍+1, copy原有buf的字符*/            expandCapacity(newcount);        }        int start = count;        count = newcount;        /** 输出字段分隔符,一般是, */        buf[start] = seperator;        int nameEnd = start + nameLen + 1;        /** 输出字段属性分隔符,一般是单引号或双引号 */        buf[start + 1] = keySeperator;        /** 输出字段名称 */        name.getChars(0, nameLen, buf, start + 2);        /** 字段名称添加分隔符,一般是单引号或双引号 */        buf[nameEnd + 1] = keySeperator;        /** 输出boolean类型字符串值 */        if (value) {            System.arraycopy(":true".toCharArray(), 0, buf, nameEnd + 2, 5);        } else {            System.arraycopy(":false".toCharArray(), 0, buf, nameEnd + 2, 6);        }    }

序列化boolean类型的键值对属性,因为不涉及特殊字符,主要就是把原型序列化为字面量值。

序列化Int类型字段键值对

public void writeFieldValue(char seperator, String name, int value) {        if (value == Integer.MIN_VALUE || !quoteFieldNames) {            /** 如果是整数最小值或不需要输出双引号,则一次输出字段分隔符,字段名字,字段值 */            write(seperator);            writeFieldName(name);            writeInt(value);            return;        }        /** 根据数字判断占用的位数,负数会多一位用于存储字符`-` */        int intSize = (value < 0) ? IOUtils.stringSize(-value) + 1 : IOUtils.stringSize(value);        int nameLen = name.length();        int newcount = count + nameLen + 4 + intSize;        if (newcount > buf.length) {            if (writer != null) {                write(seperator);                writeFieldName(name);                writeInt(value);                return;            }            /** 扩容到为原有buf容量1.5倍+1, copy原有buf的字符*/            expandCapacity(newcount);        }        int start = count;        count = newcount;        /** 输出字段分隔符,一般是, */        buf[start] = seperator;        int nameEnd = start + nameLen + 1;        /** 输出字段属性分隔符,一般是单引号或双引号 */        buf[start + 1] = keySeperator;        /** 输出字段名称 */        name.getChars(0, nameLen, buf, start + 2);        buf[nameEnd + 1] = keySeperator;        buf[nameEnd + 2] = ':';        /** 输出整数值,对整数转化成单字符 */        IOUtils.getChars(value, count, buf);    }

序列化int类型的键值对属性,因为不涉及特殊字符,主要就是把原型序列化为字面量值。截止到现在,已经把核心SerializWriter类讲完了,剩余字段键值对极其类似writeFieldValue boolean和int等,因此无需冗余分析。因为序列化真正开始之前,这个类极其基础并且非常重要,因此花的时间较多。

转载地址:http://jitci.baihongyu.com/

你可能感兴趣的文章
HDU 4333 Revolving Digits(拓展KMP)
查看>>
zoj 3587 Marlon's String(拓展KMP+dp)
查看>>
HDU 2896 病毒侵袭(AC自动机)
查看>>
poj 3468 A Simple Problem with Integers(线段树|成段更新,区间查询)
查看>>
zoj 1610 Count the Colors(线段树,成段更新染色)
查看>>
poj 2528 Mayor's posters(线段树,离散化,成段更新染色)
查看>>
CF 6E Exposition(RMQ | 线段树,二分)
查看>>
uva 11549 - Calculator Conundrum (Floyd判圈法)
查看>>
uva 1330 - City Game
查看>>
uva 1382 - Distant Galaxy
查看>>
uva 10755 - Garbage Heap(三维最大子矩阵)
查看>>
uva 1326 Jurassic Remains(中途相遇法)
查看>>
uva 1398 - Meteor
查看>>
uva 1312 - Cricket Field
查看>>
hdu 4531 吉哥系列故事——乾坤大挪移
查看>>
uva 10535 - Shooter
查看>>
uva 10730 - Antiarithmetic?
查看>>
hdu 4527 小明系列故事——玩转十滴水
查看>>
UVa 11572 - Unique Snowflakes (好题)
查看>>
UVa 11536 - Smallest Sub-Array
查看>>