【问题标题】:json4s: cross field extractionjson4s:跨域提取
【发布时间】:2018-10-10 04:12:03
【问题描述】:

json4s extract JsonAST 基于在 DefaultFormatsCustomSerializer 中定义的每种类型的规则。

有时我想进行跨域提取。例如,给定一个json字符串{"a": 1, "b": 2},我想将b的值设置为a+b。我能做到:

import org.json4s._
import org.json4s.native.JsonMethods._
import org.json4s.JsonAST._

case class A(a: Int, b: Int)

case object ACustomSerializer extends CustomSerializer[A](
    format =>
    ({
        case jo: JObject =>
            val a = (jo \ "a").extract[Int]
            val b = (jo \ "b").extract[Int] + a
            A(a, b)
    }, Map())
)

implicit val formats = DefaultFormats + ACustomSerializer

parse("""{"a": 1, "b": 2}""").extract[A] // A(1,3)

但是,如果case class A 有许多其他字段,则很难为所有字段编写规则。

case class A(a: Int, b: Int, c: Int, d: Int)

case object ACustomSerializer extends CustomSerializer[A](
    format =>
    ({
        case jo: JObject =>
            val a = (jo \ "a").extract[Int]
            val b = (jo \ "b").extract[Int] + a
            val c = ...
            val d = ...
            A(a, b, c, d)
    }, Map())
)

如果我们不想对字段 b 进行“跨字段提取”,它们可以由 DefaultFormats 或其他 CustomSerializer 处理。如果案例类实际上很大,情况会变得更糟。

有没有办法只为特殊字段编写规则,其余的由DefaultFormatsCustomSerialzer 处理?

【问题讨论】:

    标签: scala json4s


    【解决方案1】:

    一般来说,最好按原样解析数据,然后再处理(以维护separation of concerns)。

    在这种情况下,它看起来像这样:

    val a = parse("""{"a": 1, "b": 2}""").extract[A] // A(1,2)
    
    a.copy(b = a.a + a.b) // A(1,3)
    

    在更复杂的情况下,已处理数据的布局将与已解析数据不同,因此您需要第二个 case class 描述原始数据以及将其转换为已处理格式的函数。虽然这可能看起来很麻烦,但它会使代码更容易理解并且更易于修改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-29
      • 2014-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-01
      • 2018-02-14
      相关资源
      最近更新 更多