scala jackson处理任何类型,可能需要自定义拦截器

时间:2016-02-27 20:46:45

标签: java json mongodb scala

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

架构非常简单

db => case class => rest api

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

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

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

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

所以当我们从我们的遗留应用程序中收到这样的JSON时:

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

它被正确映射并产生预期类型的​​String,String。

但假设如下:

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

我们希望将此映射为String,Integer。但很明显杰克逊认为它是一个String并将其映射到String,String。

这有什么透明方式吗?我的想法,就像杰克逊的拦截器会很好,这个简单的测试

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

在这个例子中。

显然我可以编写一个通用的解析器并事先将dataformat带到正确的表单中,但我宁愿这样做透明,因为我们永远不知道用户何时会提交遗留的JSON格式,有这个bug,所以可能会破坏系统

THX

1 个答案:

答案 0 :(得分:0)

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

找到解决方案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
                     )