2

I am am parsing a json. I would like to convert it's values to other types . i.e

//json = JSON String 
val seq = net.liftweb.json.parse(json).\\("seq").values.toString.toLong
val userName = net.liftweb.json.parse(json).\\("name").values.toString
val intNum = net.liftweb.json.parse(json).\\("intId").values.toInt

I would like to cast it using generic method more "scala" way, I tried something like this:

object Converter{
  def JSONCaster[T](json:String,s:String):T={
    net.liftweb.json.parse(json).\\(s).values.toString.asInstanceOf[T]
  }
}

but got casting error :

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long at scala.runtime.BoxesRunTime.unboxToLong(Unknown Source)

1
  • There is a confusing array of competing solutions (competing libraries offering solutions) to this... Commented Jul 18, 2013 at 15:31

4 Answers 4

4

I had the same problem and remembered that Play framework had some functionality that did something similar. After digging through the source I found this Class.

Basically, we can do something like this:

object JSONCaster {

  def fromJson[T](json: String, s: String)(implicit converter: Converter[T]): T = {
    converter.convert(net.liftweb.json.parse(json).\\(s).values.toString)
  }

  trait Converter[T] { self =>
    def convert(v: String): T
  }

  object Converter{
    implicit val longLoader: Converter[Long] = new Converter[Long] {
      def convert(v: String): Long = v.toLong
    }

    implicit val stringLoader: Converter[String] = new Converter[String] {
      def convert(v: String): String = v
    }

    implicit val intLoader: Converter[Int] = new Converter[Int] {
      def convert(v: String): Long = v.toInt
    }

    // Add any other types you want to convert to, even custom types!
  }
}

Can be called like:

JSONCaster.fromJson[Long](json, "seq")

The downside is we have to define implicit converters for all the types we want to cast to. The upside being this keeps the interface really clean and reusable.

Sign up to request clarification or add additional context in comments.

Comments

1

Take a look at marshalling/unmarshalling as implemented in Spray. You may not need to reinvent the solution, and if you do, you can take a look at their source to see how they've implemented it.

Spray's marshalling/unmarshalling is similar to object graph serialization and works with more than just JSON so there's some additional inherent complexity within the implementation.

You could also get around manually parsing JSON and try lift-json.

lift-json is closer to JSON though through extract it can operate similar to Spray's marshaller/unmarshaller.

1 Comment

The json is just an example. Wanted to do a nice casting to string to generic type in scalaish [email protected]
0

The best and nice solution I found is at Derek Wyatt's Blog -heres one of the reasons why monads are awesome

Comments

0

Here I have a generic method in scala, working with liftweb / lift-json. As an idea, you need to provide the implicit Manifest.

import net.liftweb

private def jsonToObjectsSeq[T](jsonAsString: String)(implicit man: Manifest[T]): Seq[T] = {
  parse(jsonAsString)
    .children
    .map(_.extract[T])
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.