I am trying to create a dynamic parser which allows me to parse json content into different classes depending on a class name.
I will get the json and the class name (as String) and I would like to do something like this:
val theCaseClassName = "com.ardlema.JDBCDataProviderProperties"
val myCaseClass = Class.forName(theCaseClassName)
val jsonJdbcProperties = """{"url":"myUrl","userName":"theUser","password":"thePassword"}"""
val json = Json.parse(jsonJdbcProperties)
val value = Try(json.as[myClass])
The above code obviously does not compile because the json.as[] method tries to convert the node into a "T" (I have an implicit Reads[T] defined for my case class)
What would be the best way to get a proper "T" to pass in to the json.as[] method from the original String?
A great solution that might work would be to do polymorphic deserialization. This allows you to add a field (like "type") to your json and allow Jackson (assuming you're using an awesome json parser like Jackson) to figure out the proper type on your behalf. It looks like you might not be using Jackson; I promise it's worth using.
This post gives a great introduction to polymorphic types. It covers many useful cases including the case where you can't modify 3rd party code (here you add a Mixin to annotate the type hierarchy).
The simplest case ends up looking like this (and all of this works great with Scala objects too -- jackson even has a great scala module):
This generates this output:
You can also avoid listing the subtype mapping, but it requires that the json "type" field is a bit more complex. Experiment with it; you might like it. Define Animal like this:
And it produces (and consumes) json like this:
You should select your
Reads[T]
based on the class name. Unfortunately this will probably have to be a manual pattern match:Alternately, look at the implementation of
json.as
; at some point it's probably requiring aclassTag
and then calling.runtimeClass
on it. Assuming that's so, you can just do whatever it is and pass your ownmyCaseClass
there.