We have faced a situation where we needed to create Json representation for a dynamic set of fields & their values which represented by a Map[String, String].
Example:
Scala class
case class Person(name: String, age: String, customFields: Map[String,String])
Default Json representation of above class will be:
{ "name": "anil", "age": "30", "customFields": { "field1": "value1", "field2": "value2" } }
But what we wanted was:
{ "name": "anil", "age": "30", "field1": "value1", "field2": "value2" }
This was not very straight forward. While this could be possible using play framework, we didn’t want to complicate things too much. Finally we found a way to do it by returning a Map[String, String] which represents each class (it’s fields & values) using reflection and handle the behavior for custom fields separately.
case class Person(name: String, age: String, customFields:CustomFields) case class CustomFields(valueMap: Map[String,String])
def covertToMap(ref: AnyRef) = ref.getClass.getDeclaredFields.foldLeft(Map[String, Any]()){ (map, field) => { field.setAccessible(true) val value = field.get(ref) value match { case c: CustomFields => { map ++ c.valueMap } case _ => { map + (field.getName -> value) } } } }
Use the covertToMap() to convert any case class to a Map and then convert this map to normal Json using jackson json4s.
val json = Serialization.write(covertToMap(person))
Complete source code is available here