首页 > 解决方案 > 无法理解 Writes 中 contramap 的逻辑

问题描述

我无法理解将单个字段contramap编写为.case classjson

说我有一个案例类,我想创建它的 json

case class SomeThingContainer (something:SomeThing)

我会写write如下:

 implicit val somethingContainerWrites:Writes[SomeThingContainer] = (
    (JsPath \ "something").write[Something]
 ).contramap{(somethingContainer:SomeThingContainer)=>somethingContainer.something}

如果我有如下模型,则 val somethingContainerVariable = SomethingContainer(something)

在应用程序的某个地方,我会调用toJson[SomeThingContainer]将模型转换为Json. Writes[SomeThingContainer]这将寻找隐含的somethingContainerWrites. 从这里开始,如何JSON创建?如果有多个字段,我可以在一定程度上理解它unapply _的工作原理,但我无法理解contramap它的魔力如何。

标签: scalaplayframework-2.6

解决方案


contramap用于组成函子。

AWrites是一个(逆变)函子X => JsValue。(它知道如何从给定的 X 创建一个 JsValue)

显然,您已经在Writes[Something]某个地方定义了一个(因为您正在调用JsPath.write[Something]它隐含地需要它)。

在括号内,您创建一个新的Writes[Something],它只使用前者将 a 写入SomethingJSON 对象中的不同路径。

现在,要能够JsValue从 a创建 a,SomeThingContainer您需要做的就是将 a 转换SomeThingContainer为 a Something- 因为您已经有了 a Writes[Something]- 并使用它。

这就是 contramap 调用的作用:根据Writes[Something]您定义的它创建一个新Writes[SomeThingContainer]的,当给定 a 时SomeThingContainer,首先调用给定的“转换函数”生成 a Something。然后,它调用了Writes[Something]那个。

为了说明, contramap 的作用是:

Writes[X]: Functor[X => JsValue]
C: Y => X
Writes[X].contramap(C) <==> Writes[Y]: Functor[Y => X => JsValue]

推荐阅读