0

我正在使用带有 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)
}
4

3 回答 3

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)
        }
      }
    }
}
于 2014-10-24T16:23:21.937 回答
0

由于没有在所有实例上设置 id 字段,这意味着它是可选的,因此使用Optiontype 来指示它。使用字段定义您的案例类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)
        }
      }
    }
}

并且不用担心创建新对象对性能的影响。它对性能的影响可能比您想象的要小得多。您应该在改进之前测量性能。

于 2014-10-20T10:58:51.353 回答
-1

我不知道效率,但是您可以通过定义 a 来使您的代码“不那么难看”,您可以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设置为零,也就是说,如果我理解正确的话,永远不会正确。您将其设置为零的唯一原因是提取器不知道该值,因此,使用构建器,您可以显式地进行部分实例化。

于 2014-10-17T23:17:09.093 回答