如何将 JSON 表示为案例类



我想将JSON表示为案例类。

{
result:"success" or "fail"
message: "some message"
}

我的特殊要求是,result应该只取值"成功"或"错误"。任何其他值都应无法解析 JSON

我尝试创建一个特征,然后将其子类化,但我不明白如何限制result的值

sealed trait JSONResult 
case class JSONResultError(final val result:String="error") extends JSONResult
case class JSONResultSuccess(final val result:String="success") extends JSONResult
case class JsonMessages (
result: JSONResult,
message: String
)

虽然我可以创建一个 JsonMEssages 类型的变量,但我无法区分结果是JSONResultSuccess类型还是JSONResultError类型。

scala> val jm = JsonMessages(JSONResultError(),"some error message")
jm: JsonMessages = JsonMessages(JSONResultError(error),some error message)
scala>scala> jm.result.result //this doesn't work because result is of type JSONResult which hasn't got `result` though it holds object of type `JSONResultError`
<console>:13: error: value result is not a member of JSONResult
jm.result.result
^
scala> jm.result
res17: JSONResult = JSONResultError(error)

最终,我希望能够创建一个ReadsWrites如下,但我不确定这会起作用。

object JSONMessagesImplicits {
/*Writes (write to JsValue) are used by toJson method of Json object to convert data (say the model) to JsValue*/
implicit val JsonResultErrorWrites: Writes[JSONResultError] = (JsPath  "result").write[String](unlift(JSONResultError.unapply))
implicit val JsonResultSuccessWrites: Writes[JSONResultSuccess] = (JsPath  "result").write[String](unlift(JSONResultError.unapply))
implicit val JsonMessagesWithErrorWrites: Writes[JsonMessages] = (
(JsPath  "result").write[JSONResultError] and
(JsPath  "message").write[String]) (unlift(JsonMessages.unapply))
implicit val JsonMessagesWithSuccessWrites: Writes[JsonMessages] = (
(JsPath  "result").write[JSONResultSuccess] and
(JsPath  "message").write[String]) (unlift(JsonMessages.unapply))
}

错误消息非常明确:JSONResult不知道result字段,因此无法正确序列化。

JSONResult不一定是trait,仍然可以将其转换为抽象类,并且应该解决问题,例如:

sealed abstract class JsonResult(val result: String)
case class JsonResultSuccess(override val result: String = "success") extends JsonResult(result)
case class JsonResultError(override val result: String = "error") extends JsonResult(result)
case class JsonMessage(val result: JsonResult, val message: String)

然后,无需为所有内容创建单独的Write,可以缩短为:

implicit val resultWrites = new Writes[JsonMessage] {
override def writes(message: JsonMessage) : JsValue = {
Json.obj(
"result" -> message.result.result,
"message" -> message.message
)
}
}

更新

如果您仍然希望/必须使用该方法使用函数语法来定义Writes,则仍有一些简化的空间。

我认为创建JSONResult实体只是为了包装"错误"或"成功"字符串有点矫枉过正,它使进一步的映射复杂化,因为您在原始问题中看到的多个Writes

我们可以想象密封的东西如下:

sealed abstract class JsonMessage(val result: String, val message: String)
case class JsonResultSuccess(override val message: String) extends JsonMessage("success", message)
case class JsonResultFailure(override val message: String) extends JsonMessage("failure", message)

是的,message字段现在与根级别的result结合在一起;result值是后代中的常量。

我们还需要实现unapplyJsonMessage

object JsonMessage {
def unapply(jsonMessage: JsonMessage): Option[(String, String)] = {
if (jsonMessage == null) None
else Some((jsonMessage.result, jsonMessage.message))
}
}

在这些更改之后,我们只有一个Writes可以使用原始样式进行定义:

implicit val messageWrites: Writes[JsonMessage] =
((JsPath  "result").write[String] and
(JsPath  "message").write[String]) (unlift(JsonMessage.unapply))

希望这有帮助。

更新结束

最新更新