摘要:而我現在直接返回的是對象。跟進去方法,在最后調用方法將值付給和再回到前面的重寫方法最后返回轉換好的字符串。到這里整個轉換流程就已經結束了。
一、前言
最近老大說要新增一個試用廣告的功能,我巴拉巴拉的從之前推送廣告那里將代碼cv過來,然后跟老大說搞定了!過一會老大說返回的json格式不對!于是乎我瞧了瞧:
{ "adsArea1":{ "adsMaterials":[ { "animType":"99", "materialName":"b6d767d2f8ed5d21a44b0e5886680cb9.jpg", "materialType":"0", "materialUrl":"http://xxx/059492d7-66f1-4052-891a-c512f957342d22.jpg", "playTime":5, "sort":1 }], "areaDirection":"", "areaId":"3721", "areaType":"0", "createBy":"",// 空值 "createDate":"",// 空值 "deleteFlg":"",// 空值 "height":800, "id":"418", "materialList":"",// 空值 "playSettingList":"",// 空值 "updateBy":"", "updateDate":"",// 空值 "width":1280, "x":0, "y":0}, ··· }
咋看一下,感覺沒什么問題???然后他說之前返給我的格式不是這樣的,沒有這些中間的這些空值,那好吧,我看了下以往的推送歷史記錄里,確實是沒有的,那返回的是一樣的對象怎么就沒有了呢?
仔細看了下,在推送的時候,保存在推送歷史表里的記錄是轉成json字符串存儲起來的 String json = JSON.toJSONString(pushAdvertisementDto);
而存在表里的數據則沒有null值。而我現在直接返回的是對象。
那么問題就出在這里了~
點進去JSON.class里面進去看toJSONString(pushAdvertisementDto)方法 發現可以帶上一些參數:
讓我們來看看SerializerFeature是一個什么東西吧:
在網上搜索了一下名詞解釋:
就是這個東西默認是false的,默認不輸出null值的字段,如果想攜帶該字段,那么用這個方法就可以了:
JSON.toJSONString(Object object, SerializerFeature.WriteMapNullValue)
問題到這里就已經知道是為什么了,返回的數據沒有經過FastJSON轉換,因為用的是@RestController,我默認返回的對象傳回去安卓那里也是json格式,但是里面的字段不對,因為業務原因就只定義了一個 PushAdvertisementDto對象返回,所以在這里用FastJSON轉一下再返回就可以了。
我們接著往下看:
JSON.toJSONString()本質還是調的這個方法:
public static String toJSONString(Object object, int defaultFeatures, SerializerFeature... features) { SerializeWriter out = new SerializeWriter((Writer)null, defaultFeatures, features); // 1 String var5; try { JSONSerializer serializer = new JSONSerializer(out); serializer.write(object);// 2 var5 = out.toString(); } finally { out.close(); } return var5; }
1.如果我們要輸出為null值的字段,則SerializerFeature.WriteMapNullValue會被傳到SerializerWriter這里做了一個初始化:
public SerializeWriter(Writer writer, int defaultFeatures, SerializerFeature... features) { this.writer = writer; this.buf = (char[])bufLocal.get(); if (this.buf != null) { bufLocal.set((Object)null); } else { this.buf = new char[2048]; } int featuresValue = defaultFeatures; SerializerFeature[] var5 = features; int var6 = features.length; for(int var7 = 0; var7 < var6; ++var7) { SerializerFeature feature = var5[var7]; featuresValue |= feature.getMask(); } this.features = featuresValue; this.computeFeatures(); }
2.讓我們跟進來serializer.write(object); 里面看一看:
public final void write(Object object) { if (object == null) { this.out.writeNull(); } else { Class> clazz = object.getClass(); ObjectSerializer writer = this.getObjectWriter(clazz); try { writer.write(this, object, (Object)null, (Type)null, 0);// 在這里做了寫的操作 } catch (IOException var5) { throw new JSONException(var5.getMessage(), var5); } } }
跟進去writer.write(this, object, (Object)null, (Type)null, 0);
public interface ObjectSerializer { void write(JSONSerializer var1, Object var2, Object var3, Type var4, int var5) throws IOException; }
發現是個可拓展的接口,讓我們看看ObjectSerializer具體的實現類JavaBeanSerializer,這里代碼比較長,雖然重點關注的代碼比較少,但是還是完整的貼出來:
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException { SerializeWriter out = serializer.out; if (object == null) { out.writeNull(); } else if (!this.writeReference(serializer, object, features)) { FieldSerializer[] getters; if (out.sortField) { getters = this.sortedGetters; } else { getters = this.getters; } SerialContext parent = serializer.context; serializer.setContext(parent, object, fieldName, this.beanInfo.features, features); boolean writeAsArray = this.isWriteAsArray(serializer, features); try { char startSeperator = writeAsArray ? 91 : 123; char endSeperator = writeAsArray ? 93 : 125; out.append((char)startSeperator);// 這里開始拼接輸出 if (getters.length > 0 && out.isEnabled(SerializerFeature.PrettyFormat)) { serializer.incrementIndent(); serializer.println(); } boolean commaFlag = false; if ((this.beanInfo.features & SerializerFeature.WriteClassName.mask) != 0 || serializer.isWriteClassName(fieldType, object)) { Class> objClass = object.getClass(); if (objClass != fieldType) { this.writeClassName(serializer, object); commaFlag = true; } } char seperator = commaFlag ? 44 : 0; boolean directWritePrefix = out.quoteFieldNames && !out.useSingleQuotes; char newSeperator = this.writeBefore(serializer, object, (char)seperator); commaFlag = newSeperator == ","; boolean skipTransient = out.isEnabled(SerializerFeature.SkipTransientField); boolean ignoreNonFieldGetter = out.isEnabled(SerializerFeature.IgnoreNonFieldGetter); for(int i = 0; i < getters.length; ++i) { FieldSerializer fieldSerializer = getters[i]; Field field = fieldSerializer.fieldInfo.field; FieldInfo fieldInfo = fieldSerializer.fieldInfo; String fieldInfoName = fieldInfo.name; Class> fieldClass = fieldInfo.fieldClass; if ((!skipTransient || field == null || !fieldInfo.fieldTransient) && (!ignoreNonFieldGetter || field != null) && this.applyName(serializer, object, fieldInfo.name) && this.applyLabel(serializer, fieldInfo.label)) { Object propertyValue; try { propertyValue = fieldSerializer.getPropertyValue(object); } catch (InvocationTargetException var32) { if (!out.isEnabled(SerializerFeature.IgnoreErrorGetter)) { throw var32; } propertyValue = null; } if (this.apply(serializer, object, fieldInfoName, propertyValue)) { String key = this.processKey(serializer, object, fieldInfoName, propertyValue); Object originalValue = propertyValue; propertyValue = this.processValue(serializer, fieldSerializer.fieldContext, object, fieldInfoName, propertyValue); if (propertyValue != null || writeAsArray || fieldSerializer.writeNull || out.isEnabled(SerializerFeature.WriteMapNullValue)) { if (propertyValue != null && out.notWriteDefaultValue) { Class> fieldCLass = fieldInfo.fieldClass; if (fieldCLass == Byte.TYPE && propertyValue instanceof Byte && (Byte)propertyValue == 0 || fieldCLass == Short.TYPE && propertyValue instanceof Short && (Short)propertyValue == 0 || fieldCLass == Integer.TYPE && propertyValue instanceof Integer && (Integer)propertyValue == 0 || fieldCLass == Long.TYPE && propertyValue instanceof Long && (Long)propertyValue == 0L || fieldCLass == Float.TYPE && propertyValue instanceof Float && (Float)propertyValue == 0.0F || fieldCLass == Double.TYPE && propertyValue instanceof Double && (Double)propertyValue == 0.0D || fieldCLass == Boolean.TYPE && propertyValue instanceof Boolean && !(Boolean)propertyValue) { continue; } } if (commaFlag) { out.write(44); if (out.isEnabled(SerializerFeature.PrettyFormat)) { serializer.println(); } } if (key != fieldInfoName) { if (!writeAsArray) { out.writeFieldName(key, true); } serializer.write(propertyValue); } else if (originalValue != propertyValue) { if (!writeAsArray) { fieldSerializer.writePrefix(serializer); } serializer.write(propertyValue); } else { if (!writeAsArray) { if (directWritePrefix) { out.write(fieldInfo.name_chars, 0, fieldInfo.name_chars.length); } else { fieldSerializer.writePrefix(serializer); } } if (!writeAsArray) { if (fieldClass == String.class) { if (propertyValue == null) { if ((out.features & SerializerFeature.WriteNullStringAsEmpty.mask) == 0 && (fieldSerializer.features & SerializerFeature.WriteNullStringAsEmpty.mask) == 0) { out.writeNull(); } else { out.writeString(""); } } else { String propertyValueString = (String)propertyValue; if (out.useSingleQuotes) { out.writeStringWithSingleQuote(propertyValueString); } else { out.writeStringWithDoubleQuote(propertyValueString, "u0000"); } } } else { fieldSerializer.writeValue(serializer, propertyValue); } } else { fieldSerializer.writeValue(serializer, propertyValue); } } commaFlag = true; } } } } this.writeAfter(serializer, object, (char)(commaFlag ? "," : "u0000")); if (getters.length > 0 && out.isEnabled(SerializerFeature.PrettyFormat)) { serializer.decrementIdent(); serializer.println(); } out.append((char)endSeperator); // 結束拼接 } catch (Exception var33) { String errorMessage = "write javaBean error"; if (object != null) { errorMessage = errorMessage + ", class " + object.getClass().getName(); } if (fieldName != null) { errorMessage = errorMessage + ", fieldName : " + fieldName; } if (var33.getMessage() != null) { errorMessage = errorMessage + ", " + var33.getMessage(); } throw new JSONException(errorMessage, var33); } finally { serializer.context = parent; } } }
我們挑重點的看,這里我們關注out.append( )代碼就可以了,中間大致就是判斷一些前文說的SerializerFeature.WriteMapNullValue等條件。
跟進去out.append( )方法,在最后調用wirte方法將值付給this.buf 和this.count:
public void write(int c) { int newcount = this.count + 1; if (newcount > this.buf.length) { if (this.writer == null) { this.expandCapacity(newcount); } else { this.flush(); newcount = 1; } } this.buf[this.count] = (char)c; this.count = newcount; }
再回到前面的var5 = out.toString( );SerializeWriter重寫toString方法最后返回轉換好的json字符串。到這里整個json轉換流程就已經結束了。
三、結語雖然只是一開始只是json格式的一個小問題,花了挺長的時間觀看源碼,但是感覺收獲還是很大的,也很值。因為個人水平原因也不是全能看懂。。中間很長的那段源碼大致就是用反射獲取要轉成json的對象的屬性和值,然后中間經過一些條件判斷,通過輸出流拼接字符輸出字符串。
如文中有不對的地方,歡迎指出一起討論 ~
關于SerializerFeature名詞解釋源自:https://blog.csdn.net/u010246...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72922.html
摘要:前言的介紹協議使用方便,越來越流行的處理器有很多這里我介紹一下是阿里的開源框架被不少企業使用是一個極其優秀的框架地址的特點數度快無論序列化和反序列化都是當之無愧的功能強大支持普通類包括任意或零依賴沒有依賴其它任何類庫的簡單說明對于格式字符串 1.前言 1.1.FastJson的介紹: JSON協議使用方便,越來越流行,JSON的處理器有很多,這里我介紹一下FastJson,FastJs...
摘要:首先把這個示例倉庫下載到本地準備就緒,正文開始簡介以下內容基于和這兩個打包工具來展開。但是目前,中的大多數包都是以模塊的形式出現的。在它們更改之前,我們需要將模塊轉換為供處理。可以在中把注釋掉看看打包后的文件,會把整個打包進來。 本文一共七個例子,由淺入深帶你熟悉Rollup。首先把 rollup-demos 這個示例倉庫下載到本地 mkdir rollup cd rollup git...
摘要:讀取類路徑下的配置文件解析成對象數組并返回讀取類路徑下的文件先將字符串轉為數組將轉化為實體類為屬性賦值轉成實體對象實體對象包含屬性實體對象類型參考最佳實踐介紹教程 showImg(https://segmentfault.com/img/bVbaqQi?w=400&h=300); 前言 最近在開發過程中使用了大量的json作為前后端數據交換的方式,由于之前沒有對json做過系統的學習,...
摘要:配置和編碼格式使用提供過濾器處理字符編碼。請求從不改變資源的狀態,無副作用。中添加,采用默認配置已經足夠面對大多數場景注入參考鏈接手把手教你整合最優雅框架我的編碼習慣接口定義設計最佳實踐 創建項目 打開IDEA -> Create New Project勾選Create from archetypeshowImg(https://segmentfault.com/img/bV5tS4?...
閱讀 1160·2021-11-16 11:45
閱讀 1014·2021-09-04 16:41
閱讀 3076·2019-08-29 16:40
閱讀 2851·2019-08-29 15:34
閱讀 2672·2019-08-29 13:11
閱讀 1734·2019-08-29 12:58
閱讀 1725·2019-08-28 18:00
閱讀 1775·2019-08-26 18:26