序列化以下案例类时,不包括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属性是一个根据配置查找转换算法的函数,例如图像可以在本地获得,也可以从外部主机获得。
答案 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
因为id
而def apply...
我使用Asset
的{{1}}的默认值(这实际上是url
的值} id
实例化id.map( "images/" + _ + ".png")
}。
剩下的基本上只是能够重新定义Asset.apply
的噪音:事实证明,你无法重新定义案例类的工厂(你只能添加单独的重载)。所以我将该类重命名为AssetImpl
,添加了一个类型别名,以便没有人注意到(;-)),并创建了我自己的对象Asset
,我在其中定义了apply
方法(与自动生成的apply
方法不再发生冲突,因为此方法位于不同的AssetImpl
对象中。
我也可以简单地将Asset
转换为标准类(非案例类)但是我必须重新定义equals
和hashCode
,我觉得这更烦人,因为它必须保持在在课堂上添加/删除字段。