json4s:跨字段提取

时间:2018-10-10 04:12:04

标签: scala json4s

json4s ValueError: Shape must be rank 2 but is rank 1 for 'in_top_k/InTopKV2' (op: 'InTopKV2') with input shapes: [30], [30], []. JsonAST基于extractDefaultFormats中定义的每个类型的规则。

有时我想进行跨场提取。例如,给定一个json字符串CustomSerializer,我想将{"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()) ) 进行“跨字段提取”,则可以由DefaultFormats或其他CustomSerializer处理它们。如果案例类实际上很大,情况会变得更糟。

有没有一种方法可以只为特殊字段编写规则,而其余部分由bDefaultFormats处理?

1 个答案:

答案 0 :(得分:2)

通常,最好按原样解析数据,然后再处理(以维护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来描述原始数据以及将其转换为处理后格式的函数。尽管这看起来很麻烦,但是它将使代码更易于理解并且更易于修改。