如何将val元素序列化为Json

3

当序列化以下案例类时,val元素不会被包含。为什么会这样,并且我可以将其包含在内吗?

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

更新:添加了Json库,以及url“属性”的规范/预期使用。
我正在使用Play 2.1 / Scala 2.10附带的Json库。
实际上,url属性旨在成为一个函数,根据配置查找转换算法,例如图像可以从本地获取,也可以从外部主机获取。
1个回答

2

虽然你应该确切地指定你使用的json序列化库,但以下操作几乎可以保证可行:

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

鉴于url已经有了默认值,将其变成参数不会对您的代码产生负面影响(例如,您仍然可以像以前一样执行Asset(None))。唯一的缺点是现在客户端代码可能会为url创建一个具有不同值的Asset实例,这可能不是您想要的。
如果是这种情况,您可能需要为Asset类创建自定义JSON格式,但是如果不知道您使用的序列化库,则在这方面我无法提供更多帮助。
更新:
糟糕,我完全忽略了url的默认值取决于另一个参数(id)(感谢@Kristian Domagala注意到这一点)。因此,我的上面的片段无法编译。一个简单的解决方案是按照@Kristian Domagala的建议将url放在第二个参数列表中:
case class Asset(id:Option[Int],description:Option[String]=None)(val url:String = "images/" + id.toString+".png")

但这可能不是理想的,因为它改变了Asset的等同语义(在比较实例时不再考虑url),并且也改变了构造语法:当明确指定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转换为一个带有默认值NoneOption(避免了以前的编译错误,因为它不再依赖于id),在def apply...中,我使用id.map( "images/" + _ + ".png")来实例化具有默认值的urlAsset(这里实际上获取了id的值)。

其余部分基本上只是为了重新定义Asset.apply:事实证明,您实际上不能重新定义案例类的工厂(您只能添加单独的重载)。因此,我将该类重命名为AssetImpl,并添加了一个类型别名,以便没有人注意到(;-)),并创建了自己的对象Asset,在其中定义了apply方法(这不再与自动生成的apply方法冲突,因为后者在不同的AssetImpl对象中)。 我也可以简单地将Asset转换为标准类(非案例类),但这样我就必须重新定义equalshashCode,我发现这更令人烦恼,因为它必须在向类添加/删除字段时进行维护。


这段代码无法编译。要引用id,需要在第二个参数组中声明url。我最初对答案进行了负面评价,认为序列化库不会捕获第二个参数组,但事实证明Jerkson确实可以序列化它。完整的声明应该是case class Asset(id:Option[Int],description:Option[String]=None)(val url:String = "images/" + id.toString+".png")。顺便说一句,考虑到Option.toString的实现方式,我认为url的值可能不是预期的。 - Kristian Domagala
谢谢指出,我完全忽略了url->id的依赖关系。我已经更新了我的答案。 - Régis Jean-Gilles
谢谢您的回答。实际上,我最终将URL的计算移出了Asset类。我不确定接受一个我没有检查过的答案是否是正确的行为。 - rvange

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接