Json.asString возвращает None, хотя Json.toString возвращает правильное значение
Учитывая следующий класс дела 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 с этой проблемой: ссылка.
1 ответ
В цирце Json
имеет шесть asX
методы, которые соответствуют шести типам данных в JSON. Например, если Json
пример x
представляет логическое значение JSON, x.asBoolean
вернет Some
содержащий значение в виде Boolean
, но если x
является строкой, массивом, объектом, числом или нулем в формате JSON, x.asBoolean
будет пустым.
Ты видишь .asString
вернуть None
в этом случае, потому что вы называете это на Json
значение, представляющее объект JSON, а не строку JSON.
toString
метод на Json
совершенно другой: это универсальный Scala / Java toString
который в случае Json
реализован как .spaces2
, Я не уверен, что вы пытаетесь сделать здесь, но в целом я бы рекомендовал избегать toString
- если вы хотите сериализовать io.circe.Json
значение, лучше использовать принтер или методы печати, которые делают параметры форматирования более явными (например, noSpaces
, spaces2
, так далее.).
(Для чего это стоит, я не совсем доволен именованием asString
, asNull
и др. методы по Json
, В целом в Circe "как" используется в именах методов для кодирования или декодирования, что не совсем то, что происходит в этих случаях, но достаточно близко, что я никогда не удосужился придумать лучшую альтернативу.)