0

I have system where I need to serialize different kinds of objects to json and xml. Some of them are Lift MetaRecords, some are case classes. I wanted to use type classes and create something like:

trait Serializable[T] {
  serialize[T](obj: T): T
}

And usual implementations for json, xml and open for extension.

Problem I'm facing now is serialization itself. Currently there are different contexts in which objects are serialized. Imagine news feed system. There are three objects: User, Post (feed element) and Photo. Those objects have some properties and can reference each other. Now in same cases I want to serialize object alone (user settings, preferences, etc.) in other cases I need other objects to be serialized as well ie. Feed: List[Post] + related photos. In order to do that I need to provide referenced objects.

My current implementation is bloated with optional parametered functions.

def feedAsJson(post: MPost, grp: Option[PrivateGroup], commentsBox: Option[List[MPostComment]] = Empty): JObject

I thought about implementing some kind of context solution. Overload feedAsJson with implicit context parameter that will provide necessary data. I don't know how I'd like to implement it yet as it touches database maybe with cake pattern. Any suggestions very appreciated.

Lukasz
  • 3,135
  • 4
  • 20
  • 24

2 Answers2

1

Can't you put the implicits in scope that will create the right kind of serializers that you need? Something to that effect:

def doNothingSerializer[T]: Serializable[T] = ???
implicit def mpostToJson(implicit pgs:Serializable[PrivateGroup]], 
                                  cmts:Serializable[List[MPostComment]]) = 
  new Serializable[MPost] {
    def serialize(mpost: MPost): JObject = {
      val privateGroupJSon = pgs.serialize(mpost.privateGroup)
      // make the mpost json with privateGroupJSon which would be empty
      ???
    }
}

// later where you need to serialize without the inner content:
implicit val privateGroupToJson = doNothingSerializer[PrivateGroup]
implicit val mpostCommentsToJson = doNothingSerializer[List[MPostComment]]
implicitly[Serializable[MPost]].serialize(mpost)

You would need to define default serializable instances in a trait that is then inherited (so that low priority implicits are in scope).

Note that I'm assuming that the trait for Serializable is:

trait Serializable[T] {
  def serialize(t: T): JObject
}

(no [T] method type argument and returns a JObject)

Community
  • 1
  • 1
huynhjl
  • 41,520
  • 14
  • 105
  • 158
  • I want to add both Json and XML serializers hence the generic function in Serializable trait. – Lukasz Aug 06 '13 at 11:44
  • 1
    @Lukasz, then you could create two parallel hierarchies of serializers under two separate objects or package and do `import Serializable.Xml._` or `import Serializable.JSon._` in order to get the implicits. Another way is to have both `serializeXML` and a `serializeJson` methods in `Serializable`. At the very least it seems that it should be `trait Serializable[To] { def serialize[From](from: From): To }` instead of using `T` everywhere. – huynhjl Aug 06 '13 at 13:11
0

Maybe "Scala Pickling" might help you:

http://lampwww.epfl.ch/~hmiller/pickling

I just watched the presentation.

Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
earthling paul
  • 503
  • 4
  • 8
  • Serializing itself is not the problem I'm trying to solve. I need to solve code structure so its easily extensible and reusable. Then I'll plug serialization which is already done. – Lukasz Aug 07 '13 at 10:36