Come restituire Enumerator di JSON da Reactivemongo in Play 2
-
21-12-2019 - |
Domanda
Nel nostro progetto stiamo usando ReactiveMongo
con Play 2.2.1
.
Il problema è che il flusso di dati in una forma di Enumerator[A]
, restituito da ReactiveMongo
è in realtà un flusso di oggetti di valore, che non sono separati da virgole e non hanno annazioni di inizio e fine del flusso, che possono essere trattateCome apertura dell'array e dichiarazioni di chiusura.
Questo crea un problema per JSON
Consumer JS client
, dal momento che il formato previsto è
[A1,A2, ...]
Così siamo saltati in cerchi e trasformutiamo il nostro Enumeratee[A]
in Enumerator[String]
, con il controllo, se è il primo elemento, o no:
var first:Boolean = true
val aToStrs = (as.map(a => {
if(first) {
first = false;
Json.stringify(Json.toJson(a))
} else {
"," + Json.stringify(Json.toJson(a))
}
}))
Ok.chunked(
Enumerator.enumInput(Input.El("[")) andThen
aToStrs andThen
Enumerator.enumInput(Input.El("]")) andThen
Enumerator.enumInput(Input.EOF)
)
.
funziona, ma si sente come inventare la ruota.
C'è una soluzione migliore, per questo problema comune?
Soluzione
Se usi cometa o eventiOURCE non dovrai fare a mano un modo per generare un'uscita e sarai anche in grado di analizzare l'elemento di risposta per l'articolo nel client.Rispondendo con un array ti costringerà a scrivere il tuo codice di analisi o attendere fino a quando tutto è arrivato sul lato client prima di poter utilizzare la build int JSON parser nel tuo JavaScript.
Streaming con il protocollo Eventiurce è piuttosto facile con il gioco, dovresti essere in grado di fare qualcosa come:
implicit val cometEncoder = new Comet.CometMessage[JsValue](_.toString)
Ok.chunked(yourEnumerator &> EventSource()).as(EVENT_STREAM)
.
E poi nel client HTML:
<script type="text/javascript">
var es = new EventSource(jsRouter.controllers.Application.streamIt().url)
es.addEventListener("message", function (event) {
var item = JSON.parse(event.data)
// ... do something with the json value ...
})
</script>
.
C'è un esempio di questo nei progetti campione di gioco che potresti voler guardare anche $YOUR_PLAY_DIR/samples/scala/eventsource-clock/