[英]How to extract my case class from Json using Json4s?
In an akka scala applicatoon I consume a rest endpoint.在 akka scala 应用程序中,我使用了一个休息端点。 Hence, I want to map its responses to case classes, yet I also want to ease working with those case classes by transforming certain properties, eg those containing dates.
因此,我想将它的响应映射到案例类,但我也想通过转换某些属性来简化这些案例类的工作,例如那些包含日期的属性。
So given a Json:所以给定一个 Json:
{
"id": "20180213165959sCdJr",
"createdAt": "2018-02-13T16:59:59.570+0000",
"finishedAt": "2018-02-13T17:00:18.118+0000"
}
I want to create such a clase class out of it:我想从中创建这样一个类:
case class FinishedRun
(
id: String,
createdAt: Date,
finishedAt: Date
)
I created this construtor:我创建了这个构造函数:
object FinishedRun {
def apply(id: String,
createdAt: String,
finishedAt: String
): FinishedRun = {
val getDate = (jsonValue: String) => {
val format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
format.parse(jsonValue)
}
new FinishedRun(id, createdAt = getDate(createdAt), finishedAt = getDate(finishedAt))
}
}
While this works for initializing a case class from scratch, I have trouble extracting this case class with the help of the json4s libary through the parse(json).as[FinishedRun]
approach.虽然这适用于从头开始初始化案例类,但我无法在 json4s 库的帮助下通过
parse(json).as[FinishedRun]
方法提取这个案例类。
It appears that json4s does not call the case class' constructor and hence cannot extract it, throwing:看来 json4s 没有调用案例类的构造函数,因此无法提取它,抛出:
No usable value for createdAt
Invalid date '2018-02-13T16:59:59.570+0000'
org.json4s.package$MappingException: No usable value for createdAt
Invalid date '2018-02-13T16:59:59.570+0000'
at org.json4s.reflect.package$.fail(package.scala:95)
What am I missing to have Json4s parse the Date properly?我错过了什么让 Json4s 正确解析日期?
Here is my test case:这是我的测试用例:
import org.json4s._
import org.json4s.native.JsonMethods._
import org.scalatest.FlatSpec
class MarshallingTest extends FlatSpec {
implicit val formats = DefaultFormats
it should "marshall json object with date iso strings into a case class with Date properties" in {
val json =
"""
|{
| "id": "20180213165959sCdJr",
| "createdAt": "2018-02-13T16:59:59.570+0000",
| "finishedAt": "2018-02-13T17:00:18.118+0000"
|}
""".stripMargin
val expected = FinishedRun(
id = "20180213165959sCdJr",
createdAt = "2018-02-13T16:59:59.570+0000",
finishedAt = "2018-02-13T17:00:18.118+0000"
)
val actual = parse(json).extract[FinishedRun]
assert(actual == expected)
}
}
You need to define your CustomSerializer(1) , CustomSerializer(2) .您需要定义您的CustomSerializer(1) 、 CustomSerializer(2) 。 I changed the date type from Date to ZonedDateTime :
我将日期类型从Date更改为ZonedDateTime :
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import org.json4s._
import org.json4s.JsonAST._
import org.json4s.JsonDSL._
import org.json4s.native.JsonMethods._
import org.scalatest.FlatSpec
case class FinishedRun
(
id: String,
createdAt: ZonedDateTime,
finishedAt: ZonedDateTime
)
object FinishedRunSerializer {
val dateTimeFmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
}
class FinishedRunSerializer extends CustomSerializer[FinishedRun](
format => ( {
case jObj: JObject =>
implicit val fmt = format
val id = (jObj \ "id").extract[String]
val created = ZonedDateTime.parse((jObj \ "createdAt").extract[String],
FinishedRunSerializer.dateTimeFmt)
val finished = ZonedDateTime.parse((jObj \ "finishedAt").extract[String],
FinishedRunSerializer.dateTimeFmt)
FinishedRun(id, created, finished)
}, {
case finishedRun: FinishedRun =>
("id" -> finishedRun.id) ~
("createdAt" -> finishedRun.createdAt.format(FinishedRunSerializer.dateTimeFmt)) ~
("finishedAt" -> finishedRun.finishedAt.format(FinishedRunSerializer.dateTimeFmt))
}
))
In your test or the place when you use it do not forget to bring FinishedRunSerializer
:在你的测试或者使用的地方不要忘记带
FinishedRunSerializer
:
implicit val formats = DefaultFormats + new FinishedRunSerializer()
A simple solution to your problem might be to use the Serialization trait in org.json4s .您的问题的一个简单解决方案可能是使用org.json4s 中的Serialization trait。 You should be able to do something like this:
你应该能够做这样的事情:
val finishedRun = read[FinishedRun](json)
Please refer to this link for details and examples: https://github.com/json4s/json4s#serializing-polymorphic-lists有关详细信息和示例,请参阅此链接: https : //github.com/json4s/json4s#serializing-polymorphic-lists
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.