是一个现代化的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没有太多的暴力!
可是,这两个库有几个重要的区别:
java中。*
,使用javax。*
,和Android系统。*
)无用户提供类型的适配器。这是为了防止意外锁定本身特定的JDK或Android版 本。visibleCards
和使用策略类将其转换成visible_cards
,磨石要你只是名称的字段visible_cards
,由于它出如今JSON。JsonElement
模式。相反,它只是使用内置的类型,如列表
和 地图
。=
为\ u003d
默认状况下,以便它能够在HTML中被安全编码,无需额外转义。莫希天然编码它(如=
),并假定HTML编码器-若是有的话-会作本身的工做。莫希最适合当你的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
自定义类型是如何编码的某些字段,而不无处不在改变其编码。这种工做方式相似于在预选赛中的注释依赖注入工具,如匕首和吉斯。
下面是两个整数和颜色的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