[71→100]探索Android開發(fā)中將JSON轉(zhuǎn)為對(duì)應(yīng)的JavaModel的最佳實(shí)踐

JSON(JavaScript Object Notation) 是一種輕量級(jí)的數(shù)據(jù)交換格式。它基于ECMAScript的一個(gè)子集。 JSON采用完全獨(dú)立于語(yǔ)言的文本格式,但是也使用了類似于C語(yǔ)言家族的習(xí)慣(包括C蚓曼、C++脉执、C#踢代、Java盲憎、JavaScript、Perl胳挎、Python等)饼疙。這些特性使JSON成為理想的數(shù)據(jù)交換語(yǔ)言。 易于人閱讀和編寫慕爬,同時(shí)也易于機(jī)器解析和生成(一般用于提升網(wǎng)絡(luò)傳輸速率)窑眯。

Android開發(fā)基本遵從MVC模式。由于JSON的種種優(yōu)良特性医窿,使得大部分Model都從JSON轉(zhuǎn)換而來(lái)磅甩。于是把 JSON轉(zhuǎn)為對(duì)應(yīng)的JavaModel 就成移動(dòng)端開發(fā)工作很常規(guī)的一部分。

這個(gè)工作的輸入輸出很明確:
輸入 是一個(gè)json的字符串

{
  "type":"object",
  "properties": {
    "foo": {
      "type": "string"
    },
    "bar": {
      "type": "integer"
    },
    "baz": {
      "type": "boolean"
    }
  }
}

輸出 是對(duì)應(yīng)的一系列java類:

public class DataModel extends BaseModel {
    private String type;
    private PropertiesBean properties;
    
    public String getType() {
      return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public PropertiesBean getProperties() {
      return properties;
    }

    public void setProperties(PropertiesBean properties) {
        this.properties = properties;
    }
}

public static class PropertiesBean {
    private FooBean foo;
    private BarBean bar;
    private BazBean baz;

    public FooBean getFoo() {
          return foo;
      }

      public void setFoo(FooBean foo) {
          this.foo = foo;
      }

      public BarBean getBar() {
          return bar;
      }

      public void setBar(BarBean bar) {
          this.bar = bar;
      }

      public BazBean getBaz() {
          return baz;
      }

      public void setBaz(BazBean baz) {
          this.baz = baz;
      }

}

public static class FooBean {
    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

public static class BarBean {
    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

public static class BazBean {
    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

怎么完成這個(gè)轉(zhuǎn)化過(guò)程呢姥卢?

轉(zhuǎn)化方式一:復(fù)制粘貼卷要、手動(dòng)修正(最原始!6懒瘛)

對(duì)著原始的json串僧叉,把名字復(fù)制過(guò)來(lái),手動(dòng)設(shè)置每個(gè)json項(xiàng)的類型棺榔。這種方式的缺點(diǎn)非常明顯:

  1. 耗時(shí)長(zhǎng)
  2. 人工操作太多瓶堕,容易出錯(cuò),萬(wàn)一手誤把名字復(fù)制錯(cuò)了症歇,后期排除錯(cuò)誤的過(guò)程也比較麻煩郎笆。

轉(zhuǎn)化方式二:使用GsonFormat智能轉(zhuǎn)JSON

GsonFormat應(yīng)該是Android Studio上必備插件之一,先來(lái)看效果圖

效果非常的贊忘晤,而且支持過(guò)濾父類已有屬性宛蚓,這樣就不用在繼承父類后還要?jiǎng)h除相同的屬性了。它的安裝和使用方法也非常簡(jiǎn)單方便德频,具體方式參考其github主頁(yè):https://github.com/zzz40500/GsonFormat

類似插件還有一個(gè)苍息,叫JsonModelGenerator缩幸,其支持將類型為 JSONObject 和 JSONArray 的子元素拆分為單獨(dú)的實(shí)體類壹置。不過(guò)它用起來(lái)比較繁瑣,必須透過(guò)url獲取原始json串表谊,不推薦使用钞护。

由于GsonFormat的使用方式僅限于單個(gè)java類內(nèi),所以它解析產(chǎn)生的子類都是內(nèi)嵌類爆办,所以還是會(huì)需要手動(dòng)調(diào)整類的繼承關(guān)系难咕。另外每個(gè)JSON串都要先新建再轉(zhuǎn)JSON的時(shí)候,當(dāng)JSON串比較多的時(shí)候,就會(huì)覺得這一步也挺繁瑣的(程序員就是懶啊~)余佃,有沒有批量轉(zhuǎn)json的方式呢暮刃?

轉(zhuǎn)化方式三:使用JsonAnnotation批量轉(zhuǎn)JSON

JsonAnnotation利用了java annotation的特性,在Android編譯時(shí)將如下格式的代碼

String simpleStr = "{\n"
        + "    \"id\": 100,\n"
        + "    \"body\": \"It is my post\",\n"
        + "    \"number\": 0.13,\n"
        + "    \"created_at\": \"2014-05-22 19:12:38\"\n"
        + "}";
// 簡(jiǎn)單格式
@Json2Model(modelName = "SimpleModel", jsonStr = simpleStr)
String TEST_SIMPLE = "test/simple"; // api url

轉(zhuǎn)化為test.simple包下的一個(gè)類SimpleModel爆土,代碼如下:

package test.simple;

import com.google.gson.annotations.SerializedName;

public class SimpleModel {
    @SerializedName("id")
    private int id;

    @SerializedName("body")
    private String body;

    @SerializedName("created_at")
    private String createdAt;

    @SerializedName("number")
    private double number;

    public void setId(int id) {
        this.id = id;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public void setCreatedAt(String createdAt) {
        this.createdAt = createdAt;
    }

    public void setNumber(double number) {
        this.number = number;
    }

    public int getId() {
        return id;
    }

    public String getBody() {
        return body;
    }

    public String getCreatedAt() {
        return createdAt;
    }

    public double getNumber() {
        return number;
    }
}

這樣就可以批量將json轉(zhuǎn)成Model了椭懊,而且由于其只在編譯時(shí)起作用,所以并不影響程序運(yùn)行時(shí)的性能(非常棒的~)步势。具體使用方法參考其github主頁(yè):https://github.com/tianzhijiexian/JsonAnnotation

不過(guò)這種方式還是有不便利的地方氧猬,主要體現(xiàn)在兩個(gè)地方:

  1. 沒有辦法指定json對(duì)應(yīng)類的父類,因此如果Model之間有繼承關(guān)系坏瘩,需要手動(dòng)處理
  2. 不會(huì)智能判斷不同json串之間的關(guān)聯(lián)關(guān)系盅抚,因此如果Model之間有組合關(guān)系,需要手動(dòng)處理倔矾。

轉(zhuǎn)化方式四:脫離Android Studio環(huán)境轉(zhuǎn)JSON

方式三和四都基于Android Studio這個(gè)開發(fā)環(huán)境妄均,有沒有脫離這個(gè)環(huán)境直接將JSON串轉(zhuǎn)成Java Model的方式呢?
有破讨。
點(diǎn)開http://www.jsonschema2pojo.org/網(wǎng)站丛晦,可以看到如下界面:

操作很直觀清晰,可以直接將JSON轉(zhuǎn)為Model提陶,而且支持預(yù)覽烫沙,其產(chǎn)物為一系列java文件(因?yàn)閮?nèi)嵌的json對(duì)象會(huì)被解析為獨(dú)立java類)。

類似網(wǎng)站有JSON To Java

注意:這兩個(gè)網(wǎng)站都不支持批量轉(zhuǎn)JSON隙笆。

以上就是目前搜集到的所有可用資源了锌蓄,它們都是GitHub上的開源項(xiàng)目,相關(guān)地址如下:

  1. GsonFormat
  2. JsonAnnotation
  3. JsonToJava
  4. jsonschema2pojo
  5. JsonModelGenerator

目前最佳實(shí)踐清單

從目前來(lái)撑柔,最佳方式是綜合JsonAnnotationGsonFormat瘸爽。

  1. 首先利用JsonAnnotation批量生成所有的java類。
  2. 然后根據(jù)其中的組合铅忿、繼承關(guān)系進(jìn)行人工修正剪决。
  3. 當(dāng)遇到參數(shù)增刪較多的時(shí)候,用GsonFormat進(jìn)行單個(gè)操作檀训。

PS:JsonAnnotation 這個(gè)項(xiàng)目真不錯(cuò)柑潦,如果能把繼承和組合關(guān)系也解決掉,它就完美了~~

拓展閱讀:

  1. Java 注解

Panda
2016-07-06

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末峻凫,一起剝皮案震驚了整個(gè)濱河市渗鬼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荧琼,老刑警劉巖譬胎,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件差牛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡堰乔,警方通過(guò)查閱死者的電腦和手機(jī)偏化,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)镐侯,“玉大人夹孔,你說(shuō)我怎么就攤上這事∥瞿酰” “怎么了搭伤?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)袜瞬。 經(jīng)常有香客問(wèn)我怜俐,道長(zhǎng),這世上最難降的妖魔是什么邓尤? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任拍鲤,我火速辦了婚禮,結(jié)果婚禮上汞扎,老公的妹妹穿的比我還像新娘季稳。我一直安慰自己,他們只是感情好澈魄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布景鼠。 她就那樣靜靜地躺著,像睡著了一般痹扇。 火紅的嫁衣襯著肌膚如雪铛漓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天鲫构,我揣著相機(jī)與錄音浓恶,去河邊找鬼。 笑死结笨,一個(gè)胖子當(dāng)著我的面吹牛包晰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播炕吸,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼伐憾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了算途?” 一聲冷哼從身側(cè)響起塞耕,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蚀腿,失蹤者是張志新(化名)和其女友劉穎嘴瓤,沒想到半個(gè)月后扫外,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡廓脆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年筛谚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片停忿。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡驾讲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出席赂,到底是詐尸還是另有隱情吮铭,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布颅停,位于F島的核電站谓晌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏癞揉。R本人自食惡果不足惜纸肉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望喊熟。 院中可真熱鬧柏肪,春花似錦、人聲如沸芥牌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)壁拉。三九已至拐叉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扇商,已是汗流浹背凤瘦。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留案铺,地道東北人蔬芥。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像控汉,于是被迫代替她去往敵國(guó)和親笔诵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容