score:1
With colleague we have prepared a generic class that provides JSON serialization for Map[E <: Enum[E], T]
type.
The Enum
type is always converted to String
as it is required for JsObject
key
. The other parameter is generic and is converted using the implicit format: Format[T]
import play.api.data.validation.ValidationError
import play.api.libs.json._
import scala.util.{Failure, Success, Try}
class MapEnumFormat[E <: Enum[E], T](valueOf: (String => E))(implicit format: Format[T]) extends Format[Map[E, T]] {
override def writes(o: Map[E, T]): JsValue = {
JsObject(o.map { case (a, b) => (a.name, Json.toJson(b)) })
}
override def reads(json: JsValue): JsResult[Map[E, T]] = {
val result = Try(json.as[Map[String, T]].map {
case (key, value) =>
valueOf(key) -> value
})
result match {
case Success(status) =>
JsSuccess(status)
case Failure(th) =>
JsError(ValidationError(s"Error while serializing $json: $th"))
}
}
}
score:3
Note that it is mandatory for Json keys to be strings.
Following code works
Json.toJson(Map("mon" -> EnumA.MON))
Following code does not work because key for valid Json should always be string. Here the key is EnumA.Value
which is not String
.
scala> Json.toJson(Map(EnumA.MON -> "mon"))
<console>:19: error: No Json serializer found for type scala.collection.immutable.Map[EnumA.Value,String]. Try to implement an implicit Writes or Format for this type.
Json.toJson(Map(EnumA.MON -> "mon"))
But if you want it work as expected provide a writes
implicit val writes = new Writes[Map[EnumA.Value, String]] {
override def writes(o: Map[EnumA.Value, String]): JsValue = Json.toJson(o.map { case (a, b) => Json.parse(s"""{${Json.toJson(a)}:${Json.toJson(b)}}""")}.toList)
}
now following code works
Json.toJson(Map(EnumA.MON -> "hello"))
You can declare format for EnumA
as following
object EnumA extends Enumeration {
val MON = Value("monday")
val TUE = Value("Tuesday")
implicit val format = new Format[EnumA.Value] {
override def writes(o: EnumA.Value): JsValue = Json.toJson(o.toString)
override def reads(json: JsValue): JsResult[EnumA.Value] = json.validate[String].map(EnumA.withName(_))
}
}
Scala REPL output
scala> object EnumA extends Enumeration {
| val MON = Value("monday")
| val TUE = Value("Tuesday")
|
| implicit val format = new Format[EnumA.Value] {
| override def writes(o: EnumA.Value): JsValue = Json.toJson(o.toString)
| override def reads(json: JsValue): JsResult[EnumA.Value] = json.validate[String].map(EnumA.withName(_))
| }
| }
defined object EnumA
scala> Json.toJson(EnumA.MON)
res0: play.api.libs.json.JsValue = "monday"
scala> (Json.parse("""{"a": "monday"}""") \ "a").validate[EnumA.Value]
res7: play.api.libs.json.JsResult[EnumA.Value] = JsSuccess(monday,)
scala> (Json.parse("""{"a": "monday"}""") \ "a").validate[EnumA.Value].get
res10: EnumA.Value = monday
scala> Json.toJson(Map("mon" -> EnumA.MON))
res2: play.api.libs.json.JsValue = {"mon":"monday"}
scala> Json.toJson(Map(EnumA.MON -> "mon"))
<console>:19: error: No Json serializer found for type scala.collection.immutable.Map[EnumA.Value,String]. Try to implement an implicit Writes or Format for this type.
Json.toJson(Map(EnumA.MON -> "mon"))
scala> implicit val writes = new Writes[Map[EnumA.Value, String]] {
| override def writes(o: Map[EnumA.Value, String]): JsValue = Json.toJson(o.map { case (a, b) => Json.parse(s"""{${Json.toJson(a)}:${Json.toJson(b)}}""")}.toList)
| }
writes: play.api.libs.json.Writes[Map[EnumA.Value,String]] = $anon$1@65aebb67
scala> Json.toJson(Map(EnumA.MON -> "hello"))
res2: play.api.libs.json.JsValue = [{"monday":"hello"}]
Source: stackoverflow.com
Related Query
- Not able to parse Map with Enum to Json in Play Scala
- play scala json of map with list
- Scala - parse JSON data from API with ScalaJson Play Framework
- Parse json array to a case class in scala using playframework with the fields in json not matching the fields in case class
- Scala Play 2.6: Parse json with constraint between fields
- unable to convert scala map to json with play 2
- Play 2.1 Scala - JSON - Symmetric Format object with nested data structure not serializing correctly
- JsError while trying to parse JSON file into case class with Play framework API in Scala
- 2.3 Scala Play framework - Parse Json with embedded objects
- Scala type inference not working with play json
- Not able to access key-values pairs in a JSON using Play library in scala
- Scala Compiler not found in Intellij IDEA 11 with Play 2.0 project
- How to load JSON file using Play with Scala
- How to parse JSON with variable keys in Scala Play?
- Debug not working with play framework activator, scala and eclipse
- Implicit Messages Provider instance was not found in Play framework with scala
- Why I get "Application does not take parameters" using JSON Read with Play framework 2.3?
- How to parse json list or array in scala for play framework 2.2
- scala play reads parse nested json
- Scala Compiler (2.11.7) anomaly with Play JSON Writes
- How to parse json to case class with map by jsonter, plokhotnyuk
- Serialize objects with Play Scala api and Json
- How do I parse a mutableList in scala as JSON on play framework 2.0?
- How to parse an array of json in scala play framework?
- Scala play JSON mapping doesn't work with inheritance
- In Scala what is the easiest way to parse json and map to objects?
- Scala filter a sequence to map with elements that respect and not respect filter condition
- Why I parse json into a Java List, but not a Scala List?
- scala play json reads for a seal trait or enum type object
- Why can I not mix Scala code with HTML here in Play Framework 2 views?
More Query from same tag
- Install a .jar in Spark
- Unable to Send Spark Data Frame to Kafka (java.lang.ClassNotFoundException: Failed to find data source: kafka.)
- Akka Streams: How to form inlets and outlets for a Graph using a Flow
- SparkML - Creating a df(feature, feature_importance) of a RandomForestRegressionModel
- Using Scala built-in parser combinator to parse basic MIPS code
- Scala actors being passed as parameters to other actors
- Converting the following function into its tail-recursive form
- How to introduce versioning for endpoints for akka http
- How to remove the header row of spark RDD in most efficient way?
- using if instead of match on Option[X]
- How to use custom spark-defaults.conf settings
- akka http using directives outside route
- org.apache.spark.SparkException: Couldn't find leader offsets for Set([test-topic,0])
- Unable to run scala.js on PhantomJSEnv, requiresDOM setting is forced to false
- Batch scala API post requests
- What does a type have to be constrained to before it can be assigned "null"?
- Why Process0 is not defined as Process[Id, O]
- how to resolve NoSuchMethodError on typesafe config?
- Spark java.lang.UnsupportedOperationException: empty collection
- Possibility to configure Akka to use blocking or non blocking i/o?
- Converting Tab separated file to csv file
- How to combine multiple Endpoint in finch
- Scala coding styles and conventions?
- Reading a collection of lists from file in scala
- How to reference external sbt project from another sbt project?
- Skolemization of existentially typed expressions
- Spark - How to calculate percentiles in Spark 1.6 dataframe?
- How to keep the publishM2 task in sbt from adding version numbers?
- Scala : function to measure the runtime of any other function
- Finding If there is an exact mapping between two columns