[英]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.