在 Play for Scala(版本 2.3.x)中解析特殊字符(例如 è、é 和 ®)JSON

Parsing special characters (e.g., è, é, and ®) JSONs in Play for Scala (version 2.3.x)

我在 Play for Scala(版本 2.3.x)中解析特殊字符(例如 è、é 和 ®)JSON 时遇到问题。由于 Play 中的所有内容都是 UTF-8 编码的,因此上述示例(è、é 和 ®)应该不成问题。我应该提到我正在使用 IntelliJ 和 sbt 进行开发。

我已验证以下内容:

测试文件:

{"id":"295b1590-220a-11e4-b641-90e08f355b68","blah":"è é ®"}

控制器:

      def putGuid(streamId: String, guid: UUID) = Action.async(parseToEventContent) {
    implicit request =>
      render.async {
        case mimeType@(Accepts.Json()) =>
          val id = msgId.next()
          (request.body match {
            case JsonEventContent(j) =>
              eventActor ? SendEventMessages.SendJsonEvent(id, streamId, Some(guid), remoteAddress(request), j)
            case ... some other cases...
          }) map {
            case SendEventMessages.Done(`id`) => NoContent
            case ... more error cases.. blah blah ...
            case SendEventMessages.Unknown(`id`) =>
              Logger.info("Message ID: {}. Received an unknown from underlying actors", id.asInstanceOf[AnyRef])
              ServiceUnavailableRetryAfter()
          } recover exceptionErrorHandler
      } }

BodyParser 所在位置:

  trait EventContent {}
  case class JsonEventContent(data: JsValue) extends EventContent

  def parseToEventContent: BodyParser[EventContent] = BodyParser("eventContent") {
    request =>
      import play.api.libs.iteratee.Execution.Implicits.trampoline
      request.contentType match {
        case Some(MimeTypes.JSON) => parse.tolerantJson(request).map(_.right.map(JsonEventContent(_)))
        case _ => Done(Left(UnsupportedMediaType), Empty)
      }
  }

编辑#1

在我的测试中使用类似下面的东西给我“èé®”的 400 个错误,但是 "abc" 的 204 个错误(我的源文件是 utf-8 并且 javac 设置为在 build.sbt):

val eventC = Json.parse(new String(s"""{"id":"295b1590-220a-11e4-b641-90e08f355b68","blah":"è é ®"}""".getBytes("UTF-8"), "UTF-8"))
val eventCJson = eventC.toString().getBytes("UTF-8")

"return 204 when entity has è, é, ® in json event" in new WithApplication(MyFakeApplication()){
  println(s"json=${eventC}")
  val result = assertPutRequest(s"/streams/com.gilt.clickstream/events/295b1590-220a-11e4-b641-90e08f355b68", 204, event = eventCJson, "application/json", "application/json; charset=utf-8")
  contentType(result) must be equalTo None
  contentAsBytes(result) must be equalTo Array()
}

def assertPutRequest(url: String, httpStatus: Int, event: Array[Byte], acceptHeader: String = "application/json", contentTypeHeader: String = "application/json; charset=utf-8")(implicit app: Application) = {
  Akka.system.actorOf(MockEventActor.props, "event")

  val result = route(
    FakeRequest(PUT, url)
      .withHeaders(
        "Accept" -> acceptHeader,
        "Content-Type" -> contentTypeHeader)
      .withRawBody(event)
  )(new Writeable({ j: AnyContentAsRaw => j.raw.asBytes().get}, None)).get

  status(result) must be equalTo httpStatus
  result
}

解决此问题的方法是升级到 JDK 1.7。我使用的是 JDK 1.6,这导致了问题。