看板 java 關於我們 聯絡資訊
寫好了 Gson寫得不錯,專業的程式設計師寫出來的code就是不一樣 主要的概念其實也不難 就是樹狀讀JSON物件或是樹狀讀物件的欄位 然後看讀到什麼型別,再去依照欄位的型別做處理 基本上跟其他XML解析器之類的架構一樣 主要是針對gson對繼承之類的處理比較糟糕的緣故 gson跟我找到其他json工具一樣,都會把物件型別資料給丟掉 所以,在java to json這一段是ok的 但是 json to java這一段就會出問題 例如有下面這幾個 class package com.f23ko.data; class A implements IData{ String a; .....略.... } class AChild extends A{ String aChild; .....略.... } class AList implements IData{ public List<A> alist; .....略.... } Gson是看物件欄位的型別在建立實體 所以像這種狀況,Gson都沒辦法把JSON完整的轉回來 class Test{ A a=new AChile(); } 轉成JSON再把JSON轉回物件時,一定會變成 class Test{ A a=new A(); } 總之,Gson讀到物件的一個欄位時 是這樣處理的 1.讀到A ↓ A a=new AChild(); ↑ 2.呼叫處理A的Adapter去印出JSON PS.裡面有大約有二三十個Adapter在處理各種型別基礎型別 然後,如果沒有合適的Adapter,Gson會用反射把所有的欄位都去印出來 那段程式碼在 com.google.gson.internal.bind.ReflectiveTypeAdapterFactor 在把JSON轉成物件時,是這樣處理的 1.讀到A ↓ A a=new A(); ↑ 2.用反射建立A的實體 JSON "a":{"str":"字串","id":..略..} ↑ 3.找A的欄位,然後再去找JSON的同名欄位,把值塞進去 如果A沒有那個欄位,就不管 我是在JSON裡面加個標籤去識別物件類型 寫個 TypeAdapterFactory 就可以解決了 完全不用修改到Gson的Code就能解決了 總而言之,看例子: public class Demo { public static void main(String[] args) { AList list=new AList(); list.add(new A("S1")); list.add(new AChild("SC1","SC2")); System.out.println(list); //print AList[A{a:S1},AChild{a:SC1,aChild:SC2}] //problem happen when extends class Gson gson=new Gson(); String out=gson.toJson(list); System.out.println(out); //print {"alist":[{"a":"S1"},{"aChild":"SC2","a":"SC1"}]} //That is ok but.... AList list2=gson.fromJson(out,AList.class); System.out.println(list2); //print AList[A{a:S1},A{a:SC1}] // What happen? //because of Gson thought that AChile is A //so that it drop the aChild field //So I write the FDataTypeAdapterFactory to solve it //It is similar whith //com.google.gson.internal.bind.ReflectiveTypeAdapterFactor //Actually I copy that code and made a little change Gson fson=new GsonBuilder() .registerTypeAdapterFactory( new FDataTypeAdapterFactory("com.f23ko.data")) .create(); // or new FDataTypeAdapterFactory( // "objKey",IData.class,"com.f23ko.data"); // // objKey is the class Identification in the JSON string // IData.class is interface to tag the class which you want // to control // com.f23ko.data is the data class path String out2=fson.toJson(list); System.out.println(out2); //print // { // "objKey":"AList", // "alist":[ // {"objKey":"A","a":"S1"}, // {"objKey":"AChild","aChild":"SC2","a":"SC1"}] // } //objKey had memo the class type AList list3=fson.fromJson(out2, AList.class); // AList list3=(AList) fson.fromJson(out2, IData.class); // is also ok System.out.println(list3); //print AList[A{a:S1},AChild{a:SC1,aChild:SC2}] //look! It maintain the class type! } } 範例: http://f23.tw/FFG1.zip 原始碼: http://f23.tw/FFG2.zip 包好的jar: http://f23.tw/FFG3.zip -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.41.101.188 ※ 編輯: LaPass 來自: 114.41.101.188 (11/11 01:09)
dream1124:推 11/11 08:33
swpoker:JSON很隨便的~要嚴謹的要用xml會比較好 11/11 09:04
gmoz:感謝分享 11/11 09:59
swpoker:其實要去看要注入物件的型態而非在JSON塞標籤 11/11 11:34
LaPass:如果要嚴謹的話大概也只能用XML了,但是在javascript中要解 11/11 13:14
LaPass:json會方便一些,而且我之前有聽過個演講講到效率比較的問 11/11 13:17
LaPass:題,他們試到後來發現json的效率最好。所以我才選json 11/11 13:19
swpoker:json啥都沒有~當然效率最好~所以也是我的首選阿~ 11/11 13:46
Killercat:xml伔餘資料多到靠背... 而且DOM Parser也慢 11/12 12:28
PsMonkey:我還比較喜歡 YAML... Zzzz 11/12 13:03
Killercat:YAML不錯 不過普通來講JSON的壓縮率較好 11/12 17:32
jej:自訂規則弄成bite code來傳輸不是更棒~ 彈性高.. 速度快~ 11/12 17:50
LaPass:啊對了,那個演講中也有把binary列入比較,因為binary的溢 11/12 18:37
LaPass:出字元的關係,造成資料量變大,反而速度變慢 11/12 18:42
LaPass:然後,如果要把JAVA物件轉二進位的話,可以用ObjectStream 11/12 19:01
LaPass:我不建議用ObjectStream,這樣跨語言傳輸的能力會變很糟糕 11/12 20:57
Killercat:那個有嚴謹protocol 是可以跨語言讀的 只是lib要自己找 11/13 09:48
LaPass:重點就在那個要找libary.... 11/13 10:58
Killercat:說到binary 要跨語言的又要方便又要快 protobuf XD 11/13 12:44
LaPass:第一次看到這個東西,有空時我去找來看看 xd 11/13 12:51