android 中的 Moshi vs Gson

Moshi vs Gson in android

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

我一直不喜欢 Gson 的一件事是我认为它使用反射,这在 android 上可能很慢? 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,我想知道是否有任何性能提升。

Moshi 使用 Okio 优化了一些 Gson 没有的东西。

  • reading field names 时,Moshi 无需分配字符串或进行哈希查找。
  • Moshi 将输入扫描为 UTF-8 字节序列,并延迟转换为 Java 字符。例如,它永远不需要将整数文字转换为字符。

如果您已经在使用 Okio 流,那么这些优化的好处尤其明显。 Retrofit and OkHttp 的用户特别受益于 Moshi。

关于 Moshi 起源的进一步讨论在我的 post、Moshi, another JSON Processor

根据swankjesse's comment on 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. 默认情况下未安装损坏的日期适配器。

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

从之前的link可以看出,使用 moshi codegen 将创建编译时适配器来建模 classes,这将删除运行时反射的使用

型号

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

app/build.gradle

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

将生成带有验证的 MyModelJsonAdapter class 以确保模型属性的可空性。