繁体   English   中英

如何使用 json4s 解析 json 以便让原始值成为自定义案例 class?

[英]How to parse json using json4s so that let primitive values become custom case class?

我想使用案例 class 来替换 json4s 中的原始类型,因为我想将业务方法放在这些案例 class 中。

例如:

import org.json4s.{CustomSerializer, DefaultFormats, NoTypeHints}
import org.json4s.JsonAST.{JField, JInt, JObject}
import org.json4s.jackson.Serialization
import org.json4s.jackson.Serialization.read

object Json4sExercise {

  trait ObjectHolder[T] {
  }

  case class IntValue(v: Int) extends ObjectHolder[Int]

  case class StringValue(v: String) extends ObjectHolder[String]

  class IntSerializer extends CustomSerializer[IntValue](format => ( {
    case JInt(x) => IntValue(x.toInt)
  }, {
    case IntValue(x) => JInt(BigInt(x))
  }
  ))

  implicit val formats =  Serialization.formats(NoTypeHints) + new IntSerializer

  def main(args: Array[String]): Unit = {
    println(read[Map[String, _]](""" {"price":350} """))
  }

}

但不是我想要的:Map(price -> IntValue(x:350)),它打印 Map(price -> 350)

请考虑使用jsoniter-scala以提高安全性和效率。

只需将依赖项添加到您的build.sbt

libraryDependencies ++= Seq(
  "com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-core"   % "2.0.1",
  "com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-macros" % "2.0.1" % Provided // required only in compile-time
)

并使用自定义编解码器,如下面的代码所示:

trait ObjectHolder[T]

case class IntValue(v: Int) extends ObjectHolder[Int]
object IntValue {
  implicit val codec: JsonValueCodec[IntValue] = new JsonValueCodec[IntValue] {
    override def decodeValue(in: JsonReader, default:  IntValue): IntValue =
      new IntValue(in.readInt())
    override def encodeValue(x: IntValue, out: JsonWriter): Unit = 
      out.writeVal(x.v)
    override val nullValue: IntValue = new IntValue(0)
  }
}

case class StringValue(v: String) extends ObjectHolder[String]
object StringValue {
  implicit val codec: JsonValueCodec[StringValue] = new JsonValueCodec[StringValue] {
    override def decodeValue(in: JsonReader, default:  StringValue): StringValue =
      new StringValue(in.readString(default.v))
    override def encodeValue(x: StringValue, out: JsonWriter): Unit = 
      out.writeVal(x.v)
    override val nullValue: StringValue = new StringValue(null)
  }
}

case class Response(price: IntValue)
object Response {
  implicit val codec: JsonValueCodec[Response] = JsonCodecMaker.make(CodecMakerConfig)
}

val response = readFromArray[Response]("""{"price":350}""".getBytes("UTF-8"))
val json = writeToArray(Response(price = IntValue(350)))

println(response)
println(new String(json, "UTF-8"))

它应该打印:

Response(IntValue(350))
{"price":350}

您需要具体说明您要阅读的类型

println(read[Map[String, IntValue]](""" {"price":350} """))
Map(price -> IntValue(350))

如果您只想向 Scala 现有 class 添加一些自定义功能,您应该考虑使用隐式类:

implicit class IntOps(v: Int){
    def someOperation(): Int = v + 1
}

val i: Int = 1
i.someOperation()

通过这样做,您不需要将所有Int对象包装在适配器IntValue中。 此解决方案在 memory 使用方面会更好,您可以使用默认的 json 解析器,无需额外配置。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM