如何使用 Argonaut 镜头修改数字 JSON 字段?

How to modify a numeric JSON field using an Argonaut lens?

这是 Argonaut's lens documentation 上示例的简化版本:

import argonaut._, Argonaut._

val obj: Json = Parse.parseOption("""{"a":{"b":"x","c":2}}""").get

val lens1 = jObjectPL >=> jsonObjectPL("a") >=>
            jObjectPL >=> jsonObjectPL("b") >=> jStringPL

lens1.mod(_ + "y", obj)
// res0: argonaut.Json = {"a":{"b":"xy","c":2}}

如何对数字字段做类似的事情?例如,假设我们想将1添加到上面obj中的数字,得到

的结果
// res1: argonaut.Json = {"a":{"b":"x","c":3}}

我的第一次尝试是尝试

val lens2 = jObjectPL >=> jsonObjectPL("a") >=>
            jObjectPL >=> jsonObjectPL("c") >=> jNumberPL

lens2.mod(_ + 1, obj)

但是最后一行无法编译。

JsonString 在 Argonaut 中只是 String 的类型别名,但数字稍微复杂一些,因为没有核心 Scala 类型可以完美表示 JSON 中的数字。

Argonaut中的数值类型是JsonNumber,所以传给mod的第一个参数的类型需要是(JsonNumber) => JsonNumber.

具有 public 构造函数的 JsonNumber 子类型是:

  • JsonLong
  • JsonBigDecimal
  • JsonDouble

这是问题最后一行代码的更正版本,使用 JsonBigDecimal:

lens2.mod(i => JsonBigDecimal(i.toBigDecimal + 1), obj)