java - Jackson/Scala 不可变案例类 : parsing a class depending on other value in JSON

标签 java scala jackson jackson-module-scala

我有一个这样的 JSON:

{
  "switch": "foo",
  "items": [
    {"type": "one"},
    {"type": "two"}
  ]
}

我想将它加载到这样的类结构中:

case class MyFile(
  @JsonProperty("switch") _switch: String,
  @JsonProperty("items") _items: JList[Item],
) {
  val items: List[Item] = _items.toList
}

case class Item(t: String)
object Item {
  @JsonCreator
  def create(@JsonProperty("type") _type: String): Item = {
    Item(t) // <= conversion
  }
}

诀窍是我想使用某种取决于“开关”值的函数来转换传入的“类型”字符串。最简单的例子是

def create(@JsonProperty("type") _type: String): Item = {
  Item(t + "_" + switchValue)
}

但是,我似乎没有找到一种方法来在解析中访问 JSON 树的某些部分(即在构造函数中或在 @JsonCreator 静态方法中)。

到目前为止,我唯一得到的基本上是一个全局变量,例如:

case class MyFile(
  @JsonProperty("switch") _switch: String,
  @JsonProperty("items") _items: JList[Item],
) {
  MyFile.globalSwitch = _switch
  val items: List[Item] = _items.toList
}

object MyFile {
  var globalSwitch = ""
}

case class Item(t: String)
object Item {
  @JsonCreator
  def create(@JsonProperty("type") _type: String): Item = {
    Item(t + "_" + MyFile.globalSwitch) // <= conversion
  }
}

它有效,但它显然相当丑陋:例如,你不能并行解析具有不同开关值的 2 个文件等。有更好的解决方案吗?例如,也许我可以访问某种 per-ObjectMapper 或 per-parsing 上下文,我可以在其中存储此设置?

最佳答案

我认为它会对您有所帮助:https://github.com/spray/spray-json

import spray.json._
case class NamedList[A](name: String, items: List[A])
case class Item(t: String)

object MyJsonProtocol extends DefaultJsonProtocol {
  implicit def namedListFormat[A :JsonFormat] = jsonFormat2(NamedList.apply[A])
implicit val ItemDTO = jsonFormat1(Item.apply)
}
import MyJsonProtocol._
val list = NamedList[Item](name = "Alex", items = Item("Moran")::Item("Sem")::Nil)
val res = list.toJson.toString()
val parse = res.parseJson.convertTo[NamedList[Item]]

结果:

   res: String = 
{
    "name":"Alex",
    "items":
    [
      {"t":"Moran"},
      {"t":"Sem"}
    ]
}

解析:

parse: NamedList[Item] = NamedList(Alex, List(Item(Moran), Item(Sem)))

切换器可以像~~

 implicit class Switcher[A <: Item](data: NamedList[A]){
      def getEr = data.name match{
        case "Jone" => ("It`s Jone", data)
        case "Alex" => ("It`s Alex", data)
      }
     def getErFunc[T](func : (NamedList[A], String) => T) = 
         data.name match{
           case "Jone" => ("It`s Jone", func(data , "Param"))
           case "Alex" => ("It`s Alex", func(data, "Not Param"))
  }
}

val res2 = parse.getEr
val res3 = parse.getErFunc((f, s) => (f.items.size, s.toUpperCase))

结果:

res2: (String, NamedList[Item]) = 
  (It`s Alex,NamedList(Alex,List(Item(Moran), Item(Sem))))

res3: (String, (Int, String)) = (It`s Alex,(2,NOT PARAM))

关于java - Jackson/Scala 不可变案例类 : parsing a class depending on other value in JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35919540/

相关文章:

scala - Scala 中的 for 表达式与 foreach

scala - 覆盖或隐藏从父套件继承的测试

java - jackson json 到 Object 解析

java - jackson 和可迭代 : how to deserialize

java - 如何在 Mule 连接器中添加下拉列表项?

java - Android Studio 按钮进入错误页面

scala - 转置大小不均的列表

java - 在 Spring MVC 中使用 Jackson JSON 时,如何默认启用 Pascal 大小写?

java - 单击按钮时加载 XML 并以不同布局 ANDROID 显示

java - 在 Vavr 中将字符串分组在一起