How to add additional behavior only to lists of a certain type?

I have a small Scala / Neo4j app that connects people and topics through an expertAt and interest relationship. It has REST / Json Api (using Scalatra), and I ran into a typical type-erase problem when I wanted to add the asJson method for List [Person] and List [Topic]. I would like to implement different Json serialization behavior for different types of content, but of course the types are erased. The best thing I've been able to come up with so far is the following runtime trick:

implicit def topicsOrPeopleAsJson[T](list: List[T]) = new {
    def asJson: String = {
        list match {
            case head :: tail if (head.isInstanceOf[Topic]) => topicsToJson(list.asInstanceOf[List[Topic]])
            case head :: tail if (head.isInstanceOf[Person]) => peopleToJson(list.asInstanceOf[List[Person]])
            case _ => "[]"
        }
    }

    private def peopleToJson(people: List[Person]) = {
        ...
    }

    private def topicsToJson(topics: List[Topic]) = {
        ...
    }
}

This works fine, but I was wondering if there is a better solution, perhaps something, including type classes, a topic that I am not very familiar with (yet).

+3
2

( ):

trait ListToJsonConverter[T] { 
  def asJson(l: List[T]) : String 
}
implicit object PeopleToJsonConverter extends ListToJsonConverter[Person] {...}
implicit object TopicToJsonConverter extends ListToJsonConverter[Topic] {...}
implicit object DefaultJsonConverter extends ListToJsonConverter[Any] {
  def asJson(l: List[Any]) = "[]"
}
implicit def topicsOrPeopleAsJson[T](list: List[T])(implicit ev : ListToJsonConverter[T]) = new {
  def asJson = ev.asJson(list)
}

, , . . , , List [Any], .

+5

OO?

trait JSONable {
  def toJSON:String
}

class Person
class Topics

implicit def persontoJSONable(p:Person) = new PersonSerializer(p)
implicit def topicToJSONable(t:Topic) = new PersonSerializer(t)

class PersonSerializer(p:Person) extends JSONable {
  override def toJSON = {
    //...
  }
}

class TopicSerializer(t:Topic) extends JSONable {
  override def toJSON = {
    //...
  }
}

def ListAsJSON[T <% JSONable](l:List[T]) = {
  l.map(_.toJSON)
}
+4

All Articles