Re: [問題] 如何取得 基礎型別的 class ?
寫好了
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)
推
11/11 08:33, , 1F
11/11 08:33, 1F
→
11/11 09:04, , 2F
11/11 09:04, 2F
推
11/11 09:59, , 3F
11/11 09:59, 3F
→
11/11 11:34, , 4F
11/11 11:34, 4F
→
11/11 13:14, , 5F
11/11 13:14, 5F
→
11/11 13:17, , 6F
11/11 13:17, 6F
→
11/11 13:19, , 7F
11/11 13:19, 7F
→
11/11 13:46, , 8F
11/11 13:46, 8F
→
11/12 12:28, , 9F
11/12 12:28, 9F
推
11/12 13:03, , 10F
11/12 13:03, 10F
→
11/12 17:32, , 11F
11/12 17:32, 11F
→
11/12 17:50, , 12F
11/12 17:50, 12F
→
11/12 18:37, , 13F
11/12 18:37, 13F
→
11/12 18:42, , 14F
11/12 18:42, 14F
→
11/12 19:01, , 15F
11/12 19:01, 15F
→
11/12 20:57, , 16F
11/12 20:57, 16F
→
11/13 09:48, , 17F
11/13 09:48, 17F
→
11/13 10:58, , 18F
11/13 10:58, 18F
→
11/13 12:44, , 19F
11/13 12:44, 19F
→
11/13 12:51, , 20F
11/13 12:51, 20F
討論串 (同標題文章)
完整討論串 (本文為第 2 之 2 篇):
java 近期熱門文章
PTT數位生活區 即時熱門文章