我想解析Json
文件以读取可能提供的值。如果没有提供,我有默认值 fallaf back on。
显然在这种情况下,最终结果是我肯定会有一个值:从Json
读取或默认值。但是,根据我目前对ScalaJson
的了解(如果我错了,请纠正我(,我仍然必须使用Option[T]
来持有它(因为它可能直接在Json
文件中可用(。换句话说,我相信虽然我可以提供默认值,但仍必须包裹在Option[T]
有没有一种方法可以读取可选 value(使用默认(,而无需 wrap 在Option[T]
中?我想事先告知我不需要(在可预见的将来(写( serialize (我的数据到Json
中,我只需要阅读(deserialize
(Json
。bk_hr>
进一步阐述我的问题: -
我正在使用自动转换使用case class
ES,因此,不必将此case class
与给定的reads
converter
case class MyCaseClass(optString: Option[String] = Some("None"))
implicit val reads = Json.reads[MyCaseClass]
我想使用此case class
case class MyCaseClass(optStringWithDefault: String = "None")
是否可以给出相同的Json
源为此case class
编写read converter
?另外,是否有更好的设计选择可以完全克服这个问题?
我在
-
Scala 2.11.11
-
PlayFramework 2.6
如果您使用SBT,则可以在项目中包含
的spray-jsonlibraryDependencies += "io.spray" %% "spray-json" % "1.3.3"
定义案例类
case class MyCaseClass(optString: String = "None")
定义JSON转换的协议。
import spray.json._
object MyProtocol extends DefaultJsonProtocol {
implicit object MyCaseClassFormat extends RootJsonFormat[MyCaseClass] {
def write(obj: MyCaseClass): JsValue = JsObject(
"optString" -> JsString(obj.optString)
)
def read(json: JsValue): MyCaseClass = {
json.asJsObject.getFields("optString") match {
case Seq(JsString(optString)) => MyCaseClass(optString.asInstanceOf[String])
case _ => MyCaseClass()
}
}
}
}
导入协议
import MyProtocol._
方案1#
import spray.json._
val jsonStringOne: String = """{"optString": "testData"}"""
val resultOne = jsonStringOne.parseJson.convertTo[MyCaseClass]
Output: MyCaseClass(testData)
方案2#
import spray.json._
val jsonStringTwo: String = """{"otherString": "tempData"}"""
val resultTwo = jsonStringTwo.parseJson.convertTo[MyCaseClass]
Output: MyCaseClass(None)
参考链接:https://github.com/spray/spray-json
使用jsoniter-scala,它具有内置的支持案例类字段的默认值。
添加库依赖关系:
libraryDependencies ++= Seq(
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-core" % "0.29.2" % Compile,
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-macros" % "0.29.2" % Provided // required only in compile-time
)
生成用于根类型的编解码器,并将其用于解析具有默认值的案例类:
import com.github.plokhotnyuk.jsoniter_scala.macros._
import com.github.plokhotnyuk.jsoniter_scala.core._
case class Device(id: Int = 1, model: String = "iPhone X")
case class User(name: String = "Joe", devices: Seq[Device] = Seq(Device()))
implicit val codec: JsonValueCodec[User] = JsonCodecMaker.make[User](CodecMakerConfig())
val user = readFromArray("{}".getBytes)
require(user == User())