Skip to content

Instantly share code, notes, and snippets.

@milessabin
Forked from rrmckinley/gist:6324098
Last active December 21, 2015 18:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save milessabin/6345757 to your computer and use it in GitHub Desktop.
Save milessabin/6345757 to your computer and use it in GitHub Desktop.
/*
- type mismatch; found : com.tagged.vor.toJSON.type required: ?{def apply(x$1: ? >:
A): ?} Note that implicit conversions are not applicable because they are ambiguous:
both method inst1 in trait PolyInst of type [A](fn: shapeless.Poly)(implicit cse:
fn.ProductCase[shapeless.::[A,shapeless.HNil]])A => cse.Result and macro method apply
in object Poly of type (f: Any)shapeless.Poly are possible conversion functions from
com.tagged.vor.toJSON.type to ?{def apply(x$1: ? >: A): ?}
- Unable to convert expression Expr[Nothing](toJSON) to a polymorphic function
value
*/
import org.json4s._
import org.json4s.native.JsonMethods._
import shapeless._
import poly._
import ops.hlist._
// There were two problems:
// 1. object Test (or any other resolver of toJSON implicits) must follow the definition of
// toJSON if it is in the same source file.
// 2. The cases for toJSON yield result types which are much more precise than JValue,
// hence you need to specify a weaker bound on the result type required for the cases
// in the implicit argument lists for compact and pretty. Please open a ticket to add
// improved support for this case in shapeless 2.0.0-M2.
object JSON {
def compact[A](a: A)(implicit st: toJSON.Case[A] { type Result <: JValue }): String =
org.json4s.native.JsonMethods.compact(render(st(a)))
def pretty[A](a: A)(implicit st: toJSON.Case[A] { type Result <: JValue }): String =
org.json4s.native.JsonMethods.pretty(render(st(a)))
}
object toJSON extends Poly1 { // Pullback1[JValue] {
implicit def nullToJSON = at[Null](_ => JNull)
implicit def doubleToJSON = at[Double](JDouble(_))
implicit def bigIntToJSON = at[BigInt](JInt(_))
implicit def bigDecimalToJSON = at[BigDecimal](JDecimal(_))
implicit def numToJSON[V <% Long] = at[V](i => JInt(BigInt(i)))
implicit def stringToJSON = at[String](s => if (s == null) JNull else JString(s))
implicit def boolToJSON = at[Boolean](JBool(_))
implicit def jsonToJSON[V <: JValue] = at[V](identity)
implicit def dateToJSON[V <: java.util.Date](implicit f: Formats) =
at[V](s => if (s == null) JNull else JString(f.dateFormat.format(s)))
implicit def traversableToJSON[V, C[V] <: Traversable[V]](implicit st: Case.Aux[V, JValue]) =
at[C[V]](l => JArray(l.toList.map(v => toJSON(v))))
implicit def recordToJSON[R <: HList](implicit foldMap: MapFolder[R, List[JField], fieldToJSON.type]) = {
at[R](r => JObject(r.foldMap(Nil: List[JField])(fieldToJSON)(_ ::: _)))
}
}
object fieldToJSON extends Poly1 {
implicit def value[K, V: toJSON.Case] = at[(K, V)] {
case (k, v) => (keyAsString(k), toJSON(v)) :: Nil
}
implicit def option[K, V: toJSON.Case] = at[(K, Option[V])] {
case (k, Some(v)) => (keyAsString(k), toJSON(v)) :: Nil
case (k, None) => Nil
}
def keyAsString(k: Any): String = {
def isNumeric(s: String) = s.toCharArray.forall(Character.isDigit)
if (k.getClass == classOf[String]) k.toString
else {
val parts = k.getClass.getName.split("\\$")
parts.reverse.dropWhile(isNumeric).head
}
}
}
object Test {
def main(args: Array[String]) {
println(JSON.pretty("foo"))
// could not find implicit value for parameter st:
// com.tagged.vor.toJSON.Case.Aux[String,org.json4s.JValue]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment