即使Json.toString返回正确的值,Json.asString也返回None

时间:2019-02-15 08:37:32

标签: json scala circe

给出以下案例类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

这里是指向Scastie的链接,存在以下问题:link

1 个答案:

答案 0 :(得分:3)

大约Json有六个asX方法,它们对应于JSON中的六个数据类型。例如,如果Json实例x表示一个JSON布尔值,则x.asBoolean将返回一个包含值的Some的{​​{1}},但是如果{{1 }}是JSON字符串,数组,对象,数字或null,Boolean将为空。

在这种情况下,您看到x返回x.asBoolean是因为您是在代表JSON对象而不是JSON字符串的.asString值上调用它的。

None上的Json方法是完全不同的:它是通用的Scala / Java toString,在Json的情况下,它实现为toString 。我不确定您要在这里做什么,但是通常我建议避免使用Json-如果要序列化.spaces2值,最好使用打印机或打印使格式化选项更明确的方法(例如toStringio.circe.Json等)。

(出于价值考虑,我对noSpaces上的spaces2asString等方法的命名并不完全满意。通常使用“ as”在用于编码或解码的方法名称中,这并不完全是这些情况下发生的事情,但是它足够接近,以至于我从来没有想过要找到更好的选择。)