Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to receive JSON object in Ktor?

Tags:

gson

kotlin

ktor

I have data class defined, configured gson and created rout to handle post request as follows:

data class PurchaseOrder(val buyer: String, val seller: String, 
val poNumber: String, val date: String,
                     val vendorReference: String)

 install(ContentNegotiation) {
    gson {
        setDateFormat(DateFormat.LONG)
        setPrettyPrinting()
    }


    post("/purchaseOrder"){
        val po = call.receive<PurchaseOrder>()
        println("purchase order: ${po.toString()}")
        call.respondText("post received", contentType = 
        ContentType.Text.Plain)

the following JSON is sent in POST request

{
"PurchaseOrder" : {
"buyer": "buyer a",
"seller": "seller A",
"poNumber": "PO1234",
"date": "27-Jun-2018",
"vendorReference": "Ref1234"
}
}

The output shows all nulls.

purchase order: PurchaseOrder(buyer=null, seller=null, poNumber=null, 
date=null, vendorReference=null)

Reading data from call.request.receiveChannel() does show correct JSON. So I am receiving the data but call.receive() does not seem to produce expected results.

Got JSON manually and tried to create PurchaseOrder as follows bu no luck:

val channel = call.request.receiveChannel()
        val ba = ByteArray(channel.availableForRead)
        channel.readFully(ba)
        val s = ba.toString(Charset.defaultCharset())

        println(s) // prints JSON

        val gson = Gson()
        val po = gson.fromJson(s, PurchaseOrder::class.java)

        println("buyer = ${po.buyer}"  //prints null
like image 343
Tusshu Avatar asked Jul 20 '18 19:07

Tusshu


People also ask

Can we send JSON object GET request?

To get JSON from a REST API endpoint, you must send an HTTP GET request and pass the "Accept: application/json" request header to the server, which will tell the server that the client expects JSON in response.

How do I create API in KTOR?

Create a new Ktor project Name: Specify a project name. Location: Specify a directory for your project. Build System: Make sure that Gradle Kotlin is selected as a build system. Website: Leave the default example.com value as a domain used to generate a package name.


1 Answers

The problem is that you have wrapped your json in "PurchaseOrder".

If you post this instead:

{
    "buyer": "buyer a",
    "seller": "seller A",
    "poNumber": "PO1234",
    "date": "27-Jun-2018",
    "vendorReference": "Ref1234"
}

it correctly receives the following:

purchase order: PurchaseOrder(buyer=buyer a, seller=seller A, poNumber=PO1234, date=27-Jun-2018, vendorReference=Ref1234)

If you want to keep the json request as is, you have 2 options.

  1. A custom gson serializer that expects the request to be wrapped in PurchaseOrder.

  2. A wrapper class like this:

class PurchaseOrderWrapper(
    val purchaseOrder: PurchaseOrder
)

Then you can receive like this:

call.receive<PurchaseOrderWrapper>().purchaseOrder
like image 92
avolkmann Avatar answered Oct 15 '22 16:10

avolkmann