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
版權宣告:本文為博主原創文章,轉載請附上博文連結!