87

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

我一直不喜欢 Gson 的一件事是我认为它使用反射在 android 上可能很慢?Moshi 是否也使用反射?

moshi vs 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,我正在寻找是否有任何性能提升。

4

3 回答 3

104

Moshi 使用 Okio 来优化 Gson 没有做的一些事情。

  • 读取字段名称时,Moshi 不必分配字符串或进行哈希查找。
  • Moshi 将输入扫描为 UTF-8 字节序列,懒惰地转换为 Java 字符。例如,它永远不需要将整数文字转换为字符。

如果您已经在使用 Okio 流,则这些优化的好处尤其明显。RetrofitOkHttp的用户尤其受益于 Moshi。

关于 Moshi 起源的进一步讨论在我的帖子Moshi, another JSON Processor中。

于 2017-04-24T02:09:52.707 回答
46

根据swankjesse 对 reddit 的评论

我为我在 Gson 上的工作感到自豪,但也对它的一些局限性感到失望。我想解决这些问题,但不是“Gson 3.0”,部分原因是我不再在 Google 工作。Jake、Scott、Eric 和我创建了 Moshi 来解决 Gson 的各种限制。以下是比 Gson 更喜欢 Moshi 的十个小理由:

  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. 默认情况下没有安装损坏的日期适配器。

如果您正在编写新代码,我强烈建议您从 Moshi 开始。如果你有一个 Gson 的现有项目,你应该升级,如果这很简单并且没有风险。否则坚持使用Gson!我正在尽我所能确保它保持兼容和可靠。

于 2019-01-17T18:20:38.873 回答
1

从上一个链接可以看出,使用 moshi codegen 会为模型类创建编译时适配器,这将删除运行时反射的使用

模型

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

应用程序/build.gradle

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

将生成一个带有验证的 MyModelJsonAdapter 类,以确保模型属性的可空性。

于 2020-03-10T22:46:01.070 回答