When serializing the following case class, the val element is not included. Why is that, and can I have it included?
case class Asset(id: Option[Int], description: Option[String]= None) {
val url = "images/" + id.toString+".png"
}
Update: Added Json library, and specification/intended use of the url “property”.
I am using the Json library shipped with Play 2.1/Scala 2.10.
Actually the url property is meant to be a function which will look up the transformation algorithm according to configuration, for example the image can be available locally, or available from an external host.
Although you sould really specify which json serialization library you are using, it is pretty much guaranteed that just doing the following will work:
Given that
urlhas a default value anyway, turning it into a parameter won’t negatively affect your code (you can still doAsset(None)by example, as before). The only downside is that now client code might create anAssetinstance with a different value forurl, which might not be what you want.If that’s the case, you’ll probably need to create a custom json format for your
Assetclass, but without knowing which serialization library you use I can’t help much more in this respect.UPDATE:
Ooops, I totally missed the fact that the default value for
urldepends on another parameter (id) (thanks to @Kristian Domagala for noticing). Thus my above snippet does not compile. One simple solution is to puturlin a second parameter list as suggested by @Kristian Domagala:But this might not be ideal as this changed the equality semantics of
Asset(urlis not taken into account anymore when comparing instances), and also changes the construction syntax : when explicitly specifying theurlvalue, you’d need to do something likeAsset(Some(123))("gfx/myImage.png")instead of by exampleAsset(Some(123), url="gfx/myImage.png").If you can live with these downsides this is certainly the easiest solution.
Otherwise, there is another work around: we can redefine
Asset.applyourselve (by hand):As you can see I have turned
urlinto anOptionwith a default value ofNone(avoiding the previous compilation error, as it does not depend onidanymore) due to , and indef apply...I instantiateAssetwith a default value forurl(this is where I actually get the value ofid) ofid.map( "images/" + _ + ".png").The rest is basically just noise to be able to redefine
Asset.apply: it turns out that in fact you cannot redefine the factory of a case class (you can only add separate overloads). So I renamed the class asAssetImpl, added a type alias so that noone notices ( 😉 ), and created my very own objectAssetwhere I define theapplymethod (which does not conflict anymore with the auto-generatedapplymethod because this one is in the distinctAssetImplobject.I could also simply have turned
Assetinto a standard class (non case class) but then I would have to redefineequalsandhashCodewhich I find more annoying given that it must be maintained when adding/removing fields to the class.