如何在Json中序列化val元素

时间:2013-02-13 15:29:36

标签: json scala scala-2.10

序列化以下案例类时,不包括val元素。为什么会这样,我可以把它包括在内吗?

case class Asset(id: Option[Int], description: Option[String]= None) {
  val url = "images/" + id.toString+".png"
}

更新:添加了Json库,以及url“property”的规范/预期用途。

我正在使用Play 2.1 / Scala 2.10附带的Json库。

实际上,url属性是一个根据配置查找转换算法的函数,例如图像可以在本地获得,也可以从外部主机获得。

1 个答案:

答案 0 :(得分:2)

虽然您确实可以指定您正在使用哪个json序列化库,但几乎可以保证只执行以下操作:

case class Asset(id: Option[Int], description: Option[String]= None, url = "images/" + id.toString+".png")

鉴于url无论如何都有默认值,将其转换为参数不会对您的代码产生负面影响(您仍然可以像以前一样以Asset(None)为例)。唯一的缺点是,现在客户端代码可能会创建一个Asset实例,其url的值不同,这可能不是您想要的。

如果是这种情况,您可能需要为Asset类创建自定义json格式,但不知道您使用的是哪个序列化库,在这方面我无能为力。


<强>更新

哎呀,我完全错过url的默认值取决于另一个参数(id)的事实(感谢@Kristian Domagala注意到)。因此我上面的代码片段无法编译。一个简单的解决方案是将url放入@Kristian Domagala建议的第二个参数列表中:

case class Asset(id:Option[Int],description:Option[String]=None)(val url:String = "images/" + id.toString+".png")

但这可能不太理想,因为这改变了Asset的等式语义(在比较实例时不再考虑url),并且还改变了构造语法:当明确指定{时{1}}值,您需要执行url而不是示例Asset(Some(123))("gfx/myImage.png")之类的操作。 如果你能忍受这些缺点,这肯定是最简单的解决方案。

否则,还有另一项工作:我们可以重新定义Asset(Some(123), url="gfx/myImage.png")我们的十二个(手工):

Asset.apply

正如您所看到的,我已将case class AssetImpl( val id: Option[Int], val description: Option[String], val url: Option[String]) { override def productPrefix = "Asset" } type Asset = AssetImpl object Asset { def apply( id: Option[Int], description: Option[String] = None, url: Option[String] = None ) = { new Asset( id, description, url.orElse( id.map( "images/" + _ + ".png") ) ) } } 变为url,其默认值为Option(避免了之前的编译错误,因为它不依赖于None因为iddef apply...我使用Asset的{​​{1}}的默认值(这实际上是url的值} id实例化id.map( "images/" + _ + ".png") }。

剩下的基本上只是能够重新定义Asset.apply的噪音:事实证明,你无法重新定义案例类的工厂(你只能添加单独的重载)。所以我将该类重命名为AssetImpl,添加了一个类型别名,以便没有人注意到(;-)),并创建了我自己的对象Asset,我在其中定义了apply方法(与自动生成的apply方法不再发生冲突,因为此方法位于不同的AssetImpl对象中。 我也可以简单地将Asset转换为标准类(非案例类)但是我必须重新定义equalshashCode,我觉得这更烦人,因为它必须保持在在课堂上添加/删除字段。