如果我有一个JSON对象,如:
{
"test": 3
}
然后我希望提取"测试"作为字符串的字段将失败,因为类型不排队:
import org.json4s._
import org.json4s.jackson.JsonMethods
import org.json4s.JsonAST.JValue
def getVal[T: Manifest](json: JValue, fieldName: String): Option[T] = {
val field = json findField {
case JField(name, _) if name == fieldName => true
case _ => false
}
field.map {
case (_, value) => value.extract[T]
}
}
val json = JsonMethods.parse("""{"test":3}""")
val value: Option[String] = getVal[String](json, "test") // Was Some(3) but expected None
这是从JSON数字自动转换为Json4s中预期的字符串吗?如果是这样,是否有任何解决方法,其中提取的字段必须与extract
方法的type参数中指定的类型相同?
答案 0 :(得分:1)
这是大多数(如果不是全部)解析器的默认属性。如果您请求类型为T的值,并且该值可以安全地转换为该特定类型,那么库将为您投射它。例如,看看typesafe配置,其类似性质是将Numeric字段转换为String。
import com.typesafe.config._
val config = ConfigFactory parseString """{ test = 3 }"""
val res1 = config.getString("test")
res1: String = 3
如果你不想自动将Integer / Boolean强制转换为String,你可以手动检查Int / Boolean类型,如下所示。
if(Try(value.extract[Int]).isFailure || Try(value.extract[Boolean]).isFailure) {
throw RuntimeException(s"not a String field. try Int or Boolean")
} else {
value.extract[T]
}
答案 1 :(得分:0)
一个简单的解决方法是为需要“严格”行为的情况创建自定义序列化程序。例如:
import org.json4s._
val stringSerializer = new CustomSerializer[String](_ => (
{
case JString(s) => s
case JNull => null
case x => throw new MappingException("Can't convert %s to String." format x)
},
{
case s: String => JString(s)
}
))
将此序列化器添加到隐式格式中可确保严格的行为:
implicit val formats = DefaultFormats + stringSerializer
val js = JInt(123)
val str = js.extract[String] // throws MappingException