json4s使用额外数据进行对象提取

时间:2014-10-17 22:13:33

标签: json scala spray case-class json4s

我正在使用json4s的喷雾,我已经得到了下面的实现来处理更新对象的put请求...我的问题是,我首先从json中提取SomeObject的实例,但是RESTful api,我希望在URL中指定ID。所以我必须以某种方式创建另一个使用ID索引的SomeObject实例...为此,我使用像SomeObject这样的构造函数(id:Long,obj:SomeObject)。它工作得很好,但实现很难看,而且感觉效率低下。我能做什么才能以某种方式将ID粘贴在那里,以便我只创建一个SomeObject实例?

class ApplicationRouter extends BaseRouter {
  val routes =
    pathPrefix("some-path") {
      path("destination-resource" \ IntNumber) { id =>
        entity(as[JObject]) { rawData =>
          val extractedObject = rawData.camelizeKeys.extract[SomeObject]
          val extractedObjectWithId = SomeObject(id, extractedObject)
          handleRequest(extractedObjectWithId)
        }
      }
    }
}

case class SomeObject(id: Long, data: String, someValue: Double, someDate: DateTime) {
  def this(data: String, someValue: Double, someDate: DateTime) = this(0, data, someValue, someDate)
  def this(id: Long, obj: SomeObject) = this(id, obj.data, obj.someValue, obj.someDate)
}

3 个答案:

答案 0 :(得分:1)

在经过一段时间的文档挖掘后,我想出了一个解决方案:

class ApplicationRouter extends BaseRouter {
  val routes =
    pathPrefix("some-path") {
      path("destination-resource" \ IntNumber) { id =>
        entity(as[JObject]) { rawData =>
          val extractedObject = rawData.camelizeKeys.merge { 
              ("id", id)
          }.extract[SomeObject]
          handleRequest(extractedObject)
        }
      }
    }
}

答案 1 :(得分:0)

由于未在所有实例上设置id字段,因此它表示它是可选的,因此请使用Option类型来指示它。使用id: Option[Long]字段定义案例类。这使得json解析器在不存在时跳过id字段,但允许你在有时分配一个值。

case class SomeObject(id: Option[Long], data: String, someValue: Double, someDate: DateTime)

class ApplicationRouter extends BaseRouter {
  val routes =
    pathPrefix("some-path") {
      path("destination-resource" \ IntNumber) { id =>
        entity(as[JObject]) { rawData =>
          val extractedObject = rawData.camelizeKeys.extract[SomeObject]
          val extractedObjectWithId = extractedObject.copy(id = Some(id))
          handleRequest(extractedObjectWithId)
        }
      }
    }
}

并且不要担心创建新对象对性能的影响。它可能会比你想象的更少地影响性能。您应该在改进之前测量性能。

答案 2 :(得分:-1)

我不知道效率,但是你可以让你的代码变得更加难看"通过定义SomeObjectBuilder,您可以将JSON值提取到其中。

case class SomeObjectBuilder(data: String, someValue: Double, someDate: DateTime) {
  def setId(id: Long) = SomeObject(id, data, someValue, someDate)
}

case class SomeObject(id: Long, data: String, someValue: Double, someDate: DateTime) 

提取:

class ApplicationRouter extends BaseRouter {
  val routes =
    pathPrefix("some-path") {
      path("destination-resource" \ IntNumber) { id =>
        entity(as[JObject]) { rawData =>
          val extractedObject = rawData.camelizeKeys.extract[SomeObjectBuilder]
          val extractedObjectWithId = extractedObject.setId(id)
          handleRequest(extractedObjectWithId)
        }
      }
    }
}

这样,您没有将默认id设置为零,如果我理解正确,则永远不会更正。您将其设置为零的唯一原因是提取器不知道该值,因此,使用构建器,您可以显式部分实例化。