简体   繁体   中英

How do I parse a generic class parameter from JSON in Scala?

I have a generic getter trait

trait Getter[A] {
  def get: A
}

and I would like to parse JSON into a List of objects implementing this trait. Two such implementations:

case class CoalesceGetter[A](getters: List[Getter[String]]) extends Getter[A] {
  override def get: A = getters.map(_.get).find(_ != null).orNull
}

case class AsnGetter(ipGetter: Getter[String]) extends Getter[Long] {
  override def get: Long = 99L // dummy function
}

I would like to parse JSON into the correct Getter class based upon a property called function which corresponds to the class and type which corresponds to the generic type in the case of getters which need a generic (both properties are strings in the json blob I'm parsing). I've looked at custom serializers for json4s but don't see how to work with generics. Any help is appreciated!

First of all, I don't think it is a good idea to jsonify classes with type argument. I think it is a better design to define non-typed (case) classes that are direct equivalent of your json object, and use standard read/write json as provided by many libraries.

But then, to answer your question, I'd like to return another question: how would you do it "manually"? Ie how would you write and read different CoalesceGetter[A] with different A?

Here is a proposition: put the type arg in a json field:

"ofInt":   {"type-arg":"Int", "getters":[ ... list of getters in json ...]},
"ofDouble":{"type-arg":"Double", "getters":[ ... list of getters in json ...]}

Now, if you'd write the reader, how would you instantiate the 2 ofInt and ofDouble, knowing the type-arg "Int" and "Double" (which are string!).

I see 2 solutions:

1) Either you have a hard-coded map of arg-type string => actual scala type

 argType match{
   case "Int"    => new CoalesceGetter[Int](...)
   case "Double" => new CoalesceGetter[Double](...)
 }

2) Or you store and read a generalized type as string value in the arg-type string, such as the java Class.forName (see [ https://stackoverflow.com/a/7495850/1206998] for example). But this is a really really bad idea IMHO.

(note: if you want to serialize any object just to reload it later or on another computer, don't use json but dedicated serialization such as the Java Serialization or kryo that is used by spark)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM