一個現代化的JSON庫Moshi針對Android和Java

Moshi

是一個現代化的JSON庫針對Android和Java。它能夠很容易地解析JSON成Java對象:html

 
 
String json = ...; Moshi moshi = new Moshi.Builder().build(); JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class); BlackjackHand blackjackHand = jsonAdapter.fromJson(json); System.out.println(blackjackHand);

它能夠很容易地Java對象序列爲JSON:java

 
 
BlackjackHand blackjackHand = new BlackjackHand( new Card('6', SPADES), Arrays.asList(new Card('4', CLUBS), new Card('A', HEARTS))); Moshi moshi = new Moshi.Builder().build(); JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class); String json = jsonAdapter.toJson(blackjackHand); System.out.println(json);

內置型適配器

莫西已經內置了支持讀取和寫入Java的核心數據類型:git

  • 原語(整型,浮點,焦炭......)及其同行盒裝(整數,浮點數,字符...)。
  • 數組,集合,列表,集合和地圖
  • 字符串
  • 枚舉

它經過寫出來場逐場支持你的模型類。在上面的莫希例子使用這些類:github

 
 
class BlackjackHand { public final Card hidden_card; public final List<Card> visible_cards; ... } class Card { public final char rank; public final Suit suit; ... } enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES; }

讀寫此JSON:json

 
 
{
  "hidden_card": { "rank": "6", "suit": "SPADES" }, "visible_cards": [ { "rank": "4", "suit": "CLUBS" }, { "rank": "A", "suit": "HEARTS" } ] }

Javadoc中編目完整的莫西API,咱們將在下面探討。數組

自定義類型的適配器

隨着磨石,這是特別容易定製值的轉換方式,並從JSON。A型適配器是有註釋的方法,任何類@ToJson@FromJson安全

例如,磨石的一張撲克牌的默認編碼爲詳細:JSON的定義在不一樣領域的點數和花色:{「等級」:「A」,「套裝」:「心」}隨着類型的適配器,咱們能夠改變編碼的東西更緊湊:「4H」爲心中的四,「JD」爲鑽石插孔:工具

 
 
class CardAdapter { @ToJson String toJson(Card card) { return card.rank + card.suit.name().substring(0, 1); } @FromJson Card fromJson(String card) { if (card.length() != 2) throw new JsonDataException("Unknown card: " + card); char rank = card.charAt(0); switch (card.charAt(1)) { case 'C': return new Card(rank, Suit.CLUBS); case 'D': return new Card(rank, Suit.DIAMONDS); case 'H': return new Card(rank, Suit.HEARTS); case 'S': return new Card(rank, Suit.SPADES); default: throw new JsonDataException("unknown suit: " + card); } } }

註冊與該類型的適配器Moshi.Builder,咱們是好去。ui

 
 
Moshi moshi = new Moshi.Builder() .add(new CardAdapter()) .build();

Voila:編碼

{
  "hidden_card": "6S", "visible_cards": [ "4C", "AH" ] }

另外一個安卓源碼例子

須要注意的是帶註釋方法@FromJson並不須要採起一個字符串做爲參數。相反,它能夠採起任何類型的輸入和磨石將首先解析JSON到該類型的對象,而後使用@FromJson方法以產生所需的最終值。相反,帶註釋的方法@ToJson沒有產生一個字符串。

假設,例如,咱們必須分析,其中一個事件的日期和時間被表示爲兩個獨立的字符串一個JSON。

 
 
{
  "title": "Blackjack tournament", "begin_date": "20151010", "begin_time": "17:04" }

咱們想這兩個字段合併爲一個串,以方便的時間在稍後分析。同時,咱們但願有首字母大寫的全部變量名。所以,事件 咱們要莫希產生這樣的類:

 
 
class Event { String title; String beginDateAndTime; }

不用手動解析每行的JSON行(咱們也能夠作到),咱們能夠有莫希自動完成改造。咱們簡單地定義另外一個類EventJson直接對應於JSON結構:

 
 
class EventJson { String title; String begin_date; String begin_time; }

並用適當的另外一個類@FromJson@ToJson被告知莫希如何將一個轉換方法EventJson一個事件和背部。如今,每當咱們要求莫希分析一個JSON到一個事件,將首先將其解析到一個EventJson做爲一箇中間步驟。相反,序列化一個事件莫希將首先建立一個EventJson對象,而後序列化對象如常。

 
 
class EventJsonAdapter { @FromJson Event eventFromJson(EventJson eventJson) { Event event = new Event(); event.title = eventJson.title; event.beginDateAndTime = eventJson.begin_date + " " + eventJson.begin_time; return event; } @ToJson EventJson eventToJson(Event event) { EventJson json = new EventJson(); json.title = event.title; json.begin_date = event.beginDateAndTime.substring(0, 8); json.begin_time = event.beginDateAndTime.substring(9, 14); return json; } }

咱們再次註冊莫希適配器。

 
 
Moshi moshi = new Moshi.Builder() .add(new EventJsonAdapter()) .build();

如今咱們能夠用磨石直接解析JSON到一個事件

 
 
JsonAdapter<Event> jsonAdapter = moshi.adapter(Event.class); Event event = jsonAdapter.fromJson(json);

優雅地失敗

自動數據綁定幾乎感受像魔術。但不一樣的是黑魔法,一般伴隨着反射,磨石旨在幫助你當事情出錯。

 
JsonDataException: Expected one of [CLUBS, DIAMONDS, HEARTS, SPADES] but was ANCHOR at path $.visible_cards[2].suit
  at com.squareup.moshi.JsonAdapters$11.fromJson(JsonAdapters.java:188)
  at com.squareup.moshi.JsonAdapters$11.fromJson(JsonAdapters.java:180)
    ...

莫希老是拋出一個標準的java.io.IOException異常,若是有一個錯誤讀取JSON文檔,或者若是它是畸形的。它拋出一個JsonDataException若是JSON文件是良好的,但不符合預期的格式。

創建在奧基奧

莫希使用奧基奧簡單而功能強大的I / O。這是一個很好的補充,OkHttp,它能夠共享緩衝段的最大效率。

從GSON借用

莫希使用相同的流媒體和約束機制爲GSON若是你是一個GSON用戶,你會發現莫希工做方式相似。若是您嘗試莫希和不愛它,你甚至能夠遷移到GSON沒有太多的暴力!

可是,這兩個庫有幾個重要的區別:

  • 莫希具備較少的內置類型的適配器。例如,您須要配置本身的日期適配器。大多數綁定庫將編碼無論你扔他們。莫希拒絕序列化的平臺類型(java中。*使用javax。*,和Android系統。*)無用戶提供類型的適配器。這是爲了防止意外鎖定本身特定的JDK或Android版 本。
  • 莫希較少配置的。有沒有現場的命名策略,版本控制,例如創做者,或長系列化策略。相反,命名字段visibleCards和使用策略類將其轉換成visible_cards,磨石要你只是名稱的字段visible_cards,由於它出如今JSON。
  • 莫希沒有一個JsonElement模式。相反,它只是使用內置的類型,如列表和 地圖
  • 沒有HTML安全轉義。 GSON編碼=\ u003d默認狀況下,以便它能夠在HTML中被安全編碼,無需額外轉義。莫希天然編碼它(如=),並假定HTML編碼器-若是有的話-會作本身的工做。

與@Json自定義字段名稱

莫希最適合當你的JSON對象和Java對象具備相同的結構。可是,當他們不這樣作,磨石有註釋定製數據綁定。

使用@Json指定的Java如何字段映射到JSON的名字。這是必要的,當JSON名稱包含空格或者未在Java字段名稱中不容許其餘字符。例如,這個JSON有包含空格的字段名稱:

 
 
{
  "username": "jesse", "lucky number": 32 }

隨着@Json其相應的Java類很簡單:

 
 
class Player { String username; @Json(name = "lucky number") int luckyNumber; ... }

因爲JSON字段名始終與他們的Java領域的定義,磨石使得Java和JSON之間航行時很容易找到的字段。

與@JsonQualifier交替類型的適配器

使用@JsonQualifier自定義類型是如何編碼的某些字段,而不無處不在改變其編碼。這種工做方式相似於在預選賽中的註釋依賴注入工具,如匕首和吉斯。

下面是兩個整數和顏色的JSON消息:

 
 
{
  "width": 1024, "height": 768, "color": "#ff0000" }

按照慣例,Android的程序也使用INT的顏色:

 
 
class Rectangle { int width; int height; int color; }

可是,若是咱們編碼上面的Java類JSON,顏色不正確編碼!

 
 
{
  "width": 1024, "height": 768, "color": 16711680 }

解決方法是定義一個限定註解,註解自己@JsonQualifier

 
 
@Retention(RUNTIME)
@JsonQualifier public @interface HexColor { }

下一步將此@HexColor註釋相應字段:

 
class Rectangle {
  int width;
  int height;
  @HexColor int color;
}

最後定義一個類型的適配器來處理它:

 
/** Converts strings like #ff0000 to the corresponding color ints. */
class ColorAdapter {
  @ToJson String toJson(@HexColor int rgb) {
    return String.format("#%06x", rgb);
  }

  @FromJson @HexColor int fromJson(String rgb) {
    return Integer.parseInt(rgb.substring(1), 16);
  }
}

使用@JsonQualifier當您須要爲同一型號不一樣JSON編碼。大部分程序不該該須要這個@JsonQualifier,但它是爲那些確實很是方便。

下載

下載最新的JAR或經過Maven的依賴:

 
 
<dependency>
  <groupId>com.squareup.moshi</groupId> <artifactId>moshi</artifactId> <version>1.1.0</version> </dependency>

or Gradle:

compile 'com.squareup.moshi:moshi:1.1.0' 下載地址https://github.com/square/moshi/archive/master.zip
相關文章
相關標籤/搜索