作者LaPass (LaPass)
看板java
標題Re: [問題] 如何取得 基礎型別的 class ?
時間Mon Nov 11 01:03:00 2013
寫好了
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