Scala使用circe将None编码为NaN json值

Posted

技术标签:

【中文标题】Scala使用circe将None编码为NaN json值【英文标题】:Scala encoding None to NaN json value with circe 【发布时间】:2021-06-05 15:56:35 【问题描述】:

我有一个通过 HTTP 调用 TensorFlow 服务的 scala 服务。 我正在尝试使用 circe 将 None 值编码为 NaN 作为 JSON(TensorFlow 的预期方式),但是在编码对象后我得到“null”

假设我有以下需要使用 circe 序列化为 JSON 对象的案例类:

case class MyRequest(instance: Option[Double])

object MyRequest extends CirceDefaults 
  implicit val autoEncoderRequestEncoder: Encoder[MyRequest] =  (myRequest: MyRequest) =>
    myRequest.instance match 
      case Some(value) => Json.fromDouble(value).asJson
      case None => None.asJson
    
  

所以 None.asJson 编码为“null”而不是 NaN 并且我从 tensorflow 服务收到错误:

错误:无效参数:JSON 值:“null”类型:字符串不是预期类型:float”

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

这是默认的 Circe 行为。详情请查看:https://github.com/circe/circe/issues/1267

而且似乎不仅适用于 Circe,而且一般 JSON 标准没有 Nan、-Infinity、+Infinity 这样的东西,所以在 Circe 中,您甚至无法为 Double.Nan 创建 Json:https://github.com/circe/circe/blob/master/modules/core/shared/src/main/scala/io/circe/Json.scala#L517

所以Json.fromDouble(Double.Nan) 返回None - 因为Double.Nan 不是真实的:https://github.com/circe/circe/blob/master/modules/core/shared/src/main/scala/io/circe/Json.scala#L575

因此,不幸的是,为了以您想要的方式渲染 Nan,您需要在渲染后编辑 JSON 字符串

import io.circe._, io.circe.generic.semiauto._, io.circe.syntax._

case class MyRequest(instance: Option[Double])

object MyRequest 
  implicit val encoder: Encoder[MyRequest] = request => 
    request.instance.fold(Json.fromString("NaN"))(_.asJson)
  


case class BigRequest(request: MyRequest)

object BigRequest 
  implicit val encoder: Encoder[BigRequest] = deriveEncoder[BigRequest]


println(BigRequest(MyRequest(Some(1.0d))).asJson.noSpaces)

println(BigRequest(MyRequest(None)).asJson.noSpaces.replace(""""NaN"""", "NaN"))

斯卡蒂:https://scastie.scala-lang.org/SGHtB9GZRpShtQ6A8qAZsA

【讨论】:

以上是关于Scala使用circe将None编码为NaN json值的主要内容,如果未能解决你的问题,请参考以下文章

Circe Scala - 编码和解码 Map[] 和案例类

带有案例类的抽象类的scala circe编码器/解码器

使用 circe 在 Scala 中 JSON 将嵌套字段解码为 Map[String, String]

使用 circe 时如何在 Scala 中表示动态 JSON 键

如何在circe中编码/解码json的时间戳?

如何使用 circe 将密封特征案例对象转换为字符串