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 值,最好使用打印机或打印使格式化选项更明确的方法(例如 noSpacesspaces2 等)。

(就其价值而言,我对 asStringasNull 等方法在 Json 上的命名并不完全满意。一般来说 "as" 用于编码或解码的方法名称中,这在这些情况下并不完全是这样,但它足够接近以至于我从来没有费心想出更好的选择。)