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

来源:http://www.cnblogs.com/miaoqing/archive/2016/02/16/5192430.html
-Advertisement-
Play Games

Moshi 是一個現代化的JSON庫針對Android和Java。它可以很容易地解析JSON成Java對象: String json = ...; Moshi moshi = new Moshi.Builder().build(); JsonAdapter<BlackjackHand> jsonAd


Moshi

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


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:


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的核心數據類型:

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

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


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:


{
  "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,我們是好去。



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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.ERROR:--90096 :原因是:啟動圖的問題; 解決 :添加一張名字是 [email protected] 的啟動圖; 2.ERROR:--90535 :原因是:導入的第三方的問題; 解決 :刪除第三方包中的info.plist里的Executable file 這一行;
  • 在開發過程中,經常會需要處理一組不同類型的數據,比如學生的個人信息,由姓名、年齡、性別、身高等組成,因為這些數據是由不同數據類型組成的,因此不能用數組表示,對於不同數據類型的一組數據,可以採用結構體來進行存儲。當然,對於面向對象的語言來說,最好是用類來表示,但是C語言是面向過程的,因此選擇用結構體來
  • 在開始前我們在這先附一段最簡單的代碼 - (void)viewDidLoad { [super viewDidLoad]; UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; UICollec
  • 開通博客以來已經約莫1個月了。幾次想提筆寫寫東西,但總是由於各種各樣的原因並沒有開始。現在,年假剛結束,項目也還沒有開始,但最終促使我寫這篇博客的是,看了一篇博友寫的新年計劃,說是要在新的一年中寫50篇博客,我也心血來潮的定下了這樣的目標。把年前項目中用到的FragmentTabHost在這裡總結一
  • 需求:在一個數組裡面,將在這個數組中的並且在另一個數組裡面的元素過濾掉。 即:在一個數組dataArray裡面,將在dataArray數組中的並且在filteredArray數組裡面的元素過濾掉。 //iOS-篩選數組內的元素 //在dataArray中裡面,將在dataArray中的並且在filt
  • 今天早上同事說咱們的證書無法使用了,顯示“此證書的簽發者無效”。一開始以為誰誤操作了證書,查看後發現所有證書都無效了。查了會才發下原來是Apple Worldwide Developer Relations Certification Authority Intermediate Certifica
  • 嗷嗚嗷嗚嗷嗚 1 // 將視圖作為屬性方便後面執行多個不同動畫 2 _myView = [[UIView alloc] init]; 3 _myView.layer.position = CGPointMake(100, 100); 4 _myView.layer.bounds = CGRectMa
  • 今天用Xcode打包IPA文件給同事,結果提示import時,提示證書missing,找了半天沒發現問題,後來打開鑰匙串,發現證書全失效了!!!嚇死寶寶了~~~~(>_<)~~~~ 然後,處理它。 1.打開鑰匙串 2.進行如下圖操作,打開證書信息雙擊或右鍵均可 3.再次去打包,成功 註意:分享轉載請
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...