spray / spray-json

A lightweight, clean and simple JSON implementation in Scala
Apache License 2.0
974 stars 190 forks source link

Add case object format helper to SprayJsonSupport #186

Open ktoso opened 8 years ago

ktoso commented 8 years ago

Moved here from Akka.

https://github.com/akka/akka/issues/18811

@agemooij proposes something of the likes:

import spray.json._
import scala.reflect.ClassTag

/**
 * A custom version of the Spray DefaultJsonProtocol with an additional
 * formatter for ADT's of only case objects.
 */
trait CaseObjectSerializationSupport extends DefaultJsonProtocol {

  def caseObjectJsonFormat[T: ClassTag](objects: T*)(implicit tag: ClassTag[T]) = new RootJsonFormat[T] {
    /** A mapping from object names to the objects */
    private val mapping = objects.map(obj ⇒ key(obj) -> obj).toMap

    override def read(json: JsValue): T = (json match {
      case JsString(value) ⇒ mapping.get(value)
      case _               ⇒ None
    }).getOrElse(deserializationError(s"Unknown json value found when converting to $tag: $json"))

    /** The toString value of a case object is its name */
    override def write(value: T): JsValue = JsString(key(value))

    private def key(input: T): String = SimpleClassNameExtractor(input.getClass)
  }

}

object CaseObjectSerializationSupport extends CaseObjectSerializationSupport

object SimpleClassNameExtractor {
  def extractSimpleClassName(input: String) = input.split("\\.").last.split("\\$").last
  def apply[T](input: Class[T]): String = extractSimpleClassName(input.getName)
}

there too

favetelinguis commented 8 years ago

I find it rare that the same naming convention is used in case objects and json. For example MyId vs my_id etc, would be nice to be able to pass in some custom formatter that says how each name should be formatted. So in an example such as:

sealed trait Color
case object ColorAfter
case object ColorNow
case object ColorBefore

// Turn each option into snake case
implicit val formatter = sumType(Color)(snake_case)
dskrvk commented 5 years ago

What's the decision here? Are there plans to add this?

mvillafuertem commented 5 years ago

+1