Миграция для Json4S в Circe
У меня есть следующий код, написанный на json4s, который компилируется и работает нормально
import org.json4s._
def jsonRead[T <: AnyRef](input: String)(implicit m: Manifest[T]): T = {
Try(read[T](input)).get
}
def jsonWrite[T <: AnyRef](input: T)(implicit m: Manifest[T]): String = {
write[T](input).toString
}
Я написал следующий код Circe
import io.circe._
import io.circe.syntax._
import io.circe.generic.auto._
import io.circe.parser.decode
def unmarshall[T <: AnyRef](input: String)(implicit m: Manifest[T]) : T ={
decode[T](input).right.get
}
def marshall[T <: AnyRef](input: T)(implicit m: Manifest[T]) : String = {
input.asJson.toString
}
Но я получаю ошибку
Error:(27, 16) could not find implicit value for parameter decoder: io.circe.Decoder[T] decode[T](json).right.get
Error:(27, 16) not enough arguments for method decode: (implicit decoder: io.circe.Decoder[T])Either[io.circe.Error,T]. Unspecified value parameter decoder. decode[T](json).right.get
Error:(30, 11) could not find implicit value for parameter encoder: io.circe.Encoder[T] obj.asJson.toString
Error:(30, 11) not enough arguments for method asJson: (implicit encoder: io.circe.Encoder[T])io.circe.Json. Unspecified value parameter encoder. obj.asJson.toString
1 ответ
json4s
а также circe
разные библиотеки, которые работают по-разному, и поэтому вы не можете использовать одну и ту же технику. В то время как json4s
read
нужен манифест для извлечения значения из Json, circe
требуется экземпляр класса типов Decoder
, Если вы хотите использовать circe
в вашем примере вы должны написать что-то вроде
def unmarshall[T <: AnyRef](input: String)(implicit d: Decoder[T]) : T = {
decode[T](input).right.get
}
def marshall[T <: AnyRef](input: T)(implicit e: Encoder[T]) : String = {
input.asJson.toString
}
Чтобы понять различия, которые я предлагаю прочитать для обеих реализаций, очень полезно понять, как две библиотеки делают то, что делают. Вы можете увидеть различия уже в подписи json4s родной read
и Цирцея decode
, Я скопирую здесь важные биты подписей, чтобы объяснить фундаментальное различие между двумя библиотеками. Подпись родного json4s read
является
def read[A](input: String)(implicit mf: Manifest[A]): A
что можно интерпретировать как "Я могу преобразовать строку в любой тип А, если вы предоставите для этого манифест Scala". Так как Manifest
это черта Scala, используемая для размышлений, вы можете сделать вывод, что read
будет использовать отражение.
Подпись Цирцеи decode
это отличается:
def decode[A](input: String)(implicit d: Decoder[A]): Either[Error, A]
который можно прочитать как "Я могу попытаться преобразовать строку в тип A, если вы предоставите для него экземпляр Circe Decode". Decoder
класс типов просто говорит системе, как декодировать значение типа A
из JSON.