安卓开发中的Moshi和Gson对比

92

我正在决定是否使用Moshi by square或Gson来序列化和反序列化模型数据。

我一直不喜欢Gson的一件事是,我认为它使用反射在安卓上可能会很慢?Moshi也使用反射吗?

Moshi与Gson相比有哪些优缺点?

我认为它们很相似。例如,这个语句创建一个typeAdapter:

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);
    }
  }
}

并且要像在gson中一样注册它:

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

我猜优点在于注释被用于TypeAdapter。我想知道如果我切换到Moshi是否会有任何性能提升。

3个回答

112
Moshi使用Okio来优化一些Gson不能做到的事情。
  • 读取字段名称时,Moshi不需要分配字符串或进行哈希查找。
  • Moshi将输入作为UTF-8字节序列扫描,延迟地转换为Java字符。例如,它从不需要将整数文字转换为字符。
这些优化的好处特别明显,如果您已经在使用Okio流。特别是使用RetrofitOkHttp的用户受益于Moshi。
有关Moshi起源的进一步讨论,请参阅我的帖子Moshi, another JSON Processor

它是否使用反射? - j2emanue
2
作为实现细节,您自定义类的默认JsonAdapters将使用反射设置字段。 - Eric Cochran
1
@j2emanue 可以通过使用代码生成来避免反射 https://github.com/square/moshi#codegen - Pedro Lopes

50
根据swankjesse在Reddit上的评论
我对Gson的工作感到自豪,但也对其一些限制感到失望。我想解决这些问题,但不想将其称为“Gson 3.0”,部分原因是我不再在Google工作。 Jake、Scott、Eric和我创建了Moshi来解决Gson的各种限制。以下是十个选择Moshi而非Gson的小理由:
  1. 即将支持Kotlin。

  2. 限定符@HexColor int允许一个Java类型有多个JSON表示。

  3. @ToJson和@FromJson使编写和测试自定义JSON适配器变得容易。

  4. JsonAdapter.failOnUnknown()允许您拒绝意外的JSON数据。

  5. 可预测的异常。Moshi在IO问题上抛出IOException,在类型不匹配时抛出JsonDataException,而Gson则表现不一致。

  6. JsonReader.selectName()避免在常见情况下进行不必要的UTF-8解码和字符串分配。

  7. 你的APK会更小。Gson为227 KiB,Moshi+Okio总共为200 KiB。

  8. Moshi不会将平台类型的实现细节泄露到编码的JSON中。这让我对Gson感到害怕:gson.toJson(SimpleTimeZone.getTimeZone("GMT"))

  9. Moshi默认情况下不会进行奇怪的HTML转义。看看Gson对"12 & 5 = 4" 的默认编码就知道了。

  10. 默认没有损坏的Date适配器。

如果您正在编写新代码,强烈推荐使用Moshi。如果您的现有项目使用Gson,如果升级不会带来风险且简单,则应该升级。否则请继续使用Gson!我正在尽力确保它保持兼容性和可靠性。


2

从之前的链接中可以看到,使用Moshi Codegen将创建编译时适配器来处理模型类,这将在运行时消除反射的使用。

模型

@JsonClass(generateAdapter = true) 
class MyModel(val blah: Blah, val blah2: Blah)

app/build.gradle

kapt "com.squareup.moshi:moshi-kotlin-codegen:$version_moshi"

将生成一个MyModelJsonAdapter类,其中包含验证以确保模型属性的可空性。


你不觉得说 Moshi 更快吗? - j2emanue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接