A TypeScript application sends a Uint8Array
object through an HTTP POST
request to a Scala
Play
application.
How to convert the Uint8Array
object into a Scala
object in the Play
application?
For example, the TypeScript
code sends the following object:
{stuff: new Uint8Array([0, 1, 2])}
Inside the Scala
Play
controller:
case class StuffData(stuff: List[Byte])
implicit val reads: Reads[StuffData] = Json.reads[StuffData]
def processStuff = Action.async(parse.json[StuffData]) { request =>
val stuffData = request.body
println(stuffData)
}
This does not work... the error message from Play
is:
For request 'POST /send-stuff'
[Json validation error List((obj.key,List(JsonValidationError(List(error.expected.jsarray),WrappedArray()))))]
UPDATE:
To be able to get on the Scala side exactly the same byte array as was on the JavaScript side (i.e. a byte for a byte, in the original order), the current code in the accepted answer should be updated to something like:
implicit val stuffReader = new Reads[StuffData] {
def reads(js: JsValue): JsResult[StuffData] = {
JsSuccess(StuffData(
(js \ "stuff").as[Map[String, Int]].toList.sortBy(_._1.toInt).map(_._2.toByte)
))
}
}
Now, the reader populates a
case class StuffData(stuff: List[Byte])
with the same order as the original JavaScript Uint8Array
.
It's possible to convert all the Int
s into Byte
s without losing information, because we know that all the Int
s are in the range [0..255].