Skip to content

Instantly share code, notes, and snippets.

@jeffreyolchovy
Created November 30, 2010 05:50
Show Gist options
  • Save jeffreyolchovy/721229 to your computer and use it in GitHub Desktop.
Save jeffreyolchovy/721229 to your computer and use it in GitHub Desktop.
Simple type class for formatting objects as JSON or XML
package com.olchovy.format
import scala.xml._
import net.liftweb.json.JsonAST._
trait Formatter[-A, B] {
def format(a: A): B
}
object Formatters {
abstract class JsonFormatter[-A] extends Formatter[A, JValue]
implicit def a2fooJson[A](implicit ev: JsonFormatter[A]) = new FooJsonFormatter[A]
implicit def a2seqJson[A](implicit ev: JsonFormatter[A]) = new SeqJsonFormatter[A]
implicit object StringJsonFormatter extends JsonFormatter[String] {
def format(a: String) = JString(a)
}
implicit object IntJsonFormatter extends JsonFormatter[Int] {
def format(a: Int) = JInt(a)
}
implicit object DoubleJsonFormatter extends JsonFormatter[Double] {
def format(a: Double) = JDouble(a)
}
class SeqJsonFormatter[A](implicit ev: JsonFormatter[A]) extends JsonFormatter[Seq[A]] {
def format(a: Seq[A]) = JArray(a.map(ev.format(_)).toList)
}
class FooJsonFormatter[A](implicit ev: JsonFormatter[A]) extends JsonFormatter[Foo[A]] {
def format(a: Foo[A]) = JField(a.descriptor, ev.format(a.underlying))
}
abstract class XmlFormatter[-A] extends Format[A, NodeSeq]
implicit def a2fooXml[A](implicit ev: XmlFormatter[A]) = new FooXmlFormatter[A]
implicit def a2seqXml[A](implicit ev: XmlFormatter[A]) = new SeqXmlFormatter[A]
implicit object StringXmlFormatter extends XmlFormatter[String] {
def format(a: String) = Text(a)
}
implicit object IntXmlFormatter extends XmlFormatter[Int] {
def format(a: Int) = Text(a.toString)
}
implicit object DoubleXmlFormatter extends XmlFormatter[Double] {
def format(a: Double) = Text(a.toString)
}
class SeqXmlFormatter[A](implicit ev: XmlFormatter[A]) extends XmlFormatter[Seq[A]] {
def format(a: Seq[A]) = new NodeSeq {
def theSeq = a.map {
a => Elem(null, "item", Null, TopScope, ev.format(a).theSeq: _*)
}.flatMap(a => a)
}
}
class FooXmlFormatter[A](implicit ev: XmlFormatter[A]) extends XmlFormatter[Foo[A]] {
def format(a: Foo[A]) = {
val label = a.descriptor
val child = ev.format(a.underlying).theSeq
Elem(null, label, Null, TopScope, child: _*)
}
}
}
abstract class Foo[+A] {
val descriptor: String
val underlying: A
def format[B](implicit ev: Formatter[Foo[A], B]) = ev.format(this)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment