2016-05-04 49 views
2

我試圖定義HttpService接收JSON並將其與json4s庫解析到案例類:http4s - get請求體String或InputStream的

import org.http4s._ 
import org.http4s.dsl._ 
import org.json4s._ 
import org.json4s.native.JsonMethods._ 

case class Request(firstName: String, secondName: String) 

HttpService { 
    case req @ POST -> Root => 
    val request = parse(<map req.body or req.bodyAsText to JsonInput>).extract[Request] 
    Ok() 
} 

我怎樣才能從req.bodyreq.bodyAsTextorg.json4s.JsonInput

我知道json4s也有StringInputStreamInputJsonInput繼承與StringInputStream使用,所以我想,我需要req.body轉換爲InputStreamreq.bodyAsTextString,但我還是不明白如何。

我是新來的斯卡拉,我還沒有完全理解一些概念,如scalaz.stream.Process

回答

2

可以使用http4s-json4s-jackson(或http4s-json4s-native)封裝,並使用org.http4s.EntityDecoder輕鬆獲得Foo從一個請求(我改名爲你Request情況下,類下面Foo)。

EntityDecoder是一種可以從請求主體中解碼實體的類型類。 我們希望獲得以JSON發佈的Foo,所以我們需要創建一個可以解碼JSON的EntityDecoder[Foo]。如果我們想用json4s創建這個解碼器,我們需要一個Reader(或者一個JsonFormat)。

如果您有一個EntityDecoder[Foo]實例,我們可以從req.as[Foo]請求中獲得Foo

import org.json4s._ 
import org.json4s.jackson.JsonMethods._ 

import org.http4s._ 
import org.http4s.dsl._ 
import org.http4s.json4s.jackson._ 

case class Foo(firstName: String, secondName: String) 

// create a json4s Reader[Foo] 
implicit val formats = DefaultFormats 
implicit val fooReader = new Reader[Foo] { 
    def read(value: JValue): Foo = value.extract[Foo] 
} 
// create a http4s EntityDecoder[Foo] (which uses the Reader) 
implicit val fooDec = jsonOf[Foo] 

val service = HttpService { 
    case req @ POST -> Root => 
    // req.as[Foo] gives us a Task[Foo] 
    // and since Ok(...) gives a Task[Response] we need to use flatMap 
    req.as[Foo] flatMap (foo => Ok(foo.firstName + " " + foo.secondName)) 
} 

注:最常用與http4s的JSON庫庫是可能argonautcirce。所以你可能會發現更多使用這些庫的http4s示例。

2

Peter的解決方案既糾正了問題,也回答了問題,但我在這裏偶然發現尋找解決OP的陳述,但不是打算的問題:「如何在http4s中獲得請求主體作爲InputStream」。由於在Issue 634 GitHub上的討論,這裏就是我想出了:

import java.io.InputStream 
import org.http4s._ 
implicit val inputStreamDecoder: EntityDecoder[InputStream] = 
    EntityDecoder.decodeBy(MediaRange.`*/*`) { msg => 
    DecodeResult.success(scalaz.stream.io.toInputStream(msg.body)) 
} 

,然後在HttpService的,使用解碼器,像這樣:

request.as[InputStream].flatMap { inputStream => ...inputStream is an InputStream... } 

或跳過整個解碼器舞,如果你想要:

val inputStream = scalaz.stream.io.toInputStream(request.body)