【问题标题】:scala jackson dealing with any type, possible custom interceptor requiredscala jackson 处理任何类型,可能需要自定义拦截器
【发布时间】:2016-02-27 20:46:44
【问题描述】:

我目前正在重写我们的一个应用程序,它使用 PostgreSQL,现在应该使用 Mongo。

架构非常简单

db => case class => rest api

我们正在使用 scala jackson,一切正常,除了一些小烦恼,我只是在寻找正确的方法。

考虑这个案例类来理解我的烦恼

case class Test(val id:String, val value:Any)

此时,我们应用程序中的值可以是数字或字符串,数字可以是 Integer 或 Double。

所以当我们从旧版应用程序接收到这样的 JSON 时:

{ id:"a",value:"test"}

它被正确映射并产生预期的字符串类型,字符串。

但假设如下:

{ id:"b", value:"1"}

我们希望将其映射到 String,Integer。但显然jackson认为它是一个String,并将其映射到String,String。

有没有一些透明的方法来做到这一点?我的想法,会是类似于jackson的拦截器会很好,简单的测试

if type.isDouble == true return double value
else if type.isInteger == true return integer value
else return string value

所以我们最终会得到

String,Double
String,Integer
String,String

在这个例子中。

显然我可以编写一个通用解析器并预先将数据格式转换为正确的形式,但我宁愿这样做透明,因为我们永远不知道用户何时会提交遗留的 JSON 格式,有这个错误,因此可能会破坏系统。

谢谢

【问题讨论】:

  • 嗯,“1”是一个字符串,而且由于 MongoDB 支持numeric types,如果它以这种方式检索文档,则插入数据时会出现问题,而不仅仅是读取时。
  • 正确,这是我们的传统格式,在 mongo 之前。因此,当用户提交旧格式时,我们会自动转换它

标签: java json mongodb scala


【解决方案1】:

好的,看起来这比预期的要容易,只需编写一个客户序列化程序并注释我们需要它的一个字段

找到解决方案here

实际例子:

class NumberDeserializer extends JsonDeserializer[Any] {
  override def deserialize(jsonParser: JsonParser, deserializationContext: DeserializationContext): Any = {
    val jsonNode: JsonNode = jsonParser.getCodec.readTree(jsonParser)

    val content = jsonNode.textValue

    try {
      content.toInt
    } catch {
      case e: NumberFormatException => try {
        content.toDouble
      }
      catch {
        case e2: NumberFormatException => content
      }
    }
  }
}

用法:

case class Test(
                   @JsonDeserialize(using = classOf[NumberDeserializer])
                   value: Any
                     )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    • 2013-12-30
    • 2020-10-11
    相关资源
    最近更新 更多