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 "как" используется в именах методов для кодирования или декодирования, что не совсем то, что происходит в этих случаях, но достаточно близко, что я никогда не удосужился придумать лучшую альтернативу.)

Другие вопросы по тегам