Json.asString returns None 尽管 Json.toString returns 是正确的值
Json.asString returns None even though Json.toString returns the correct value
给定以下情况 class LogMessage
:
import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import enumeratum.{CirceEnum, Enum, EnumEntry}
import io.circe.syntax._
sealed trait LogLevel extends EnumEntry
object LogLevel extends Enum[LogLevel] with CirceEnum[LogLevel] {
val values = findValues
case object Warning extends LogLevel
case object Error extends LogLevel
case object Info extends LogLevel
case object Success extends LogLevel
}
object LogMessage {
implicit val logMessageDecoder: Decoder[LogMessage] = deriveDecoder[LogMessage]
implicit val logMessageEncoder: Encoder[LogMessage] = deriveEncoder[LogMessage]
}
case class LogMessage(level: LogLevel, text: String, args: List[String], date: Long)
case class MyClass[A](obj: A)(implicit encoder: Encoder[A]) {
def message1: String = obj.asJson.toString
def message2: Option[String] = obj.asJson.asString
}
为什么这样做:
val x = MyClass(LogMessage(LogLevel.Info, "test notification", Nil, 1550218866571))
x.message1 // {\n "level" : "Info",\n "text" : "test notification",\n "args" : [\n ],\n "date" : 1550218866571\n}
但这不是:
x.message2 // None
这里是 link 给 Scastie 的这个问题:link。
In circe Json
有六个asX
方法对应JSON中的六种数据类型。例如,如果 Json
实例 x
表示 JSON 布尔值,则 x.asBoolean
将 return 包含值为 [=16] 的 Some
=],但如果 x
是 JSON 字符串、数组、对象、数字或 null,则 x.asBoolean
将为空。
在这种情况下,您会看到 .asString
return None
,因为您在代表 JSON 对象的 Json
值上调用它,不是 JSON 字符串。
Json
上的 toString
方法完全不同:它是通用的 Scala / Java toString
,在 Json
的情况下实现作为 .spaces2
。我不确定你想在这里做什么,但一般来说我建议避免使用 toString
——如果你想序列化一个 io.circe.Json
值,最好使用打印机或打印使格式化选项更明确的方法(例如 noSpaces
、spaces2
等)。
(就其价值而言,我对 asString
、asNull
等方法在 Json
上的命名并不完全满意。一般来说 "as" 用于编码或解码的方法名称中,这在这些情况下并不完全是这样,但它足够接近以至于我从来没有费心想出更好的选择。)
给定以下情况 class LogMessage
:
import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import enumeratum.{CirceEnum, Enum, EnumEntry}
import io.circe.syntax._
sealed trait LogLevel extends EnumEntry
object LogLevel extends Enum[LogLevel] with CirceEnum[LogLevel] {
val values = findValues
case object Warning extends LogLevel
case object Error extends LogLevel
case object Info extends LogLevel
case object Success extends LogLevel
}
object LogMessage {
implicit val logMessageDecoder: Decoder[LogMessage] = deriveDecoder[LogMessage]
implicit val logMessageEncoder: Encoder[LogMessage] = deriveEncoder[LogMessage]
}
case class LogMessage(level: LogLevel, text: String, args: List[String], date: Long)
case class MyClass[A](obj: A)(implicit encoder: Encoder[A]) {
def message1: String = obj.asJson.toString
def message2: Option[String] = obj.asJson.asString
}
为什么这样做:
val x = MyClass(LogMessage(LogLevel.Info, "test notification", Nil, 1550218866571))
x.message1 // {\n "level" : "Info",\n "text" : "test notification",\n "args" : [\n ],\n "date" : 1550218866571\n}
但这不是:
x.message2 // None
这里是 link 给 Scastie 的这个问题:link。
In circe Json
有六个asX
方法对应JSON中的六种数据类型。例如,如果 Json
实例 x
表示 JSON 布尔值,则 x.asBoolean
将 return 包含值为 [=16] 的 Some
=],但如果 x
是 JSON 字符串、数组、对象、数字或 null,则 x.asBoolean
将为空。
在这种情况下,您会看到 .asString
return None
,因为您在代表 JSON 对象的 Json
值上调用它,不是 JSON 字符串。
Json
上的 toString
方法完全不同:它是通用的 Scala / Java toString
,在 Json
的情况下实现作为 .spaces2
。我不确定你想在这里做什么,但一般来说我建议避免使用 toString
——如果你想序列化一个 io.circe.Json
值,最好使用打印机或打印使格式化选项更明确的方法(例如 noSpaces
、spaces2
等)。
(就其价值而言,我对 asString
、asNull
等方法在 Json
上的命名并不完全满意。一般来说 "as" 用于编码或解码的方法名称中,这在这些情况下并不完全是这样,但它足够接近以至于我从来没有费心想出更好的选择。)