在 Json4s 中,为什么 JSON 对象中的整数字段会自动转换为字符串?
In Json4s why does an integer field in a JSON object get automatically converted to a String?
如果我有一个 JSON 对象,例如:
{
"test": 3
}
然后我预计将 "test" 字段提取为字符串会失败,因为类型不一致:
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
方法的类型参数中指定的类型相同?
这是大多数(如果不是全部)解析器的默认特性。如果您请求类型 T 的值,并且该值可以安全地转换为该特定类型,那么该库将为您转换它。例如,看一下类型安全配置,它具有将数字字段转换为字符串的类似性质。
import com.typesafe.config._
val config = ConfigFactory parseString """{ test = 3 }"""
val res1 = config.getString("test")
res1: String = 3
如果您不想自动将 Integer/Boolean 转换为字符串,您可以像下面这样手动检查 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]
}
一个简单的解决方法是为需要 "strict" 行为的情况创建自定义序列化程序。例如:
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
如果我有一个 JSON 对象,例如:
{
"test": 3
}
然后我预计将 "test" 字段提取为字符串会失败,因为类型不一致:
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
方法的类型参数中指定的类型相同?
这是大多数(如果不是全部)解析器的默认特性。如果您请求类型 T 的值,并且该值可以安全地转换为该特定类型,那么该库将为您转换它。例如,看一下类型安全配置,它具有将数字字段转换为字符串的类似性质。
import com.typesafe.config._
val config = ConfigFactory parseString """{ test = 3 }"""
val res1 = config.getString("test")
res1: String = 3
如果您不想自动将 Integer/Boolean 转换为字符串,您可以像下面这样手动检查 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]
}
一个简单的解决方法是为需要 "strict" 行为的情况创建自定义序列化程序。例如:
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