scalasbtakkaakka-http

Scala Akka HTTP problem accessing post request parameters


I'm trying to create a Post request path using the Akka HTTP Server and the Scala programming language.

But after I successfully make the request, I find it difficult to access the values of the request body parameters.

I would like to access the values of parameters h, w of Impression and domain of Site.

What is the best way to access these parameters?

I am using SprayJSON as the marshaller.

The current code val h =bid_request_params.imp.h gives the error value h is not a member of Option[List[com.example.WebServer.Impression]].

Again, the request is processed successfully, I just can't figure out how to access the values of the parameters.

The code is as below.

The case classes:


case class Site(id: String, domain: String)

case class Impression(id: String, h: Int, w: Int)

case class MyRequest(id: String, imp: Option[List[Impression]], site: Site)

The Post Request path:


path("submit") {
   post {
    entity(as[MyRequest]) { bid_request_params =>
    val h = bid_request_params.imp.h
    val w = bid_request_params.imp.w
    val w = bid_request_params.site.domain
    }
  }
}

The request body:


{
 "id": "SGu1Jpq1IO",
 "site": {
       "id": "0006a522f",
       "domain": "btmn.tld"
  },
 "imp": [{
       "id": "1",
       "h": 250,
       "w": 300
  }]
}


Solution

  • The problem you have, is how you are trying to access the value of the imp field of type Option[List[Impression]].

    Based on how you defined your case classes, you would have something like this if you try to manually create an instance of MyRequest

    case class Site(id: String, domain: String)
    case class Impression(id: String, h: Int, w: Int)
    case class MyRequest(id: String, imp: Option[List[Impression]], site: Site)
    
    val request = MyRequest(
      id = "SGu1Jpq1IO",
      site = Site(
        id = "0006a522f",
        domain = "btmn.tld"
      ),
      imp = Some(       // here you have an Option
        List(           // here you have the List
          Impression(   // here is the Impression class you define
            id = "1",
            h = 250,
            w = 300
          )
        )
      )
    )
    

    when you try to do something like

    val h = request // MyRequest
              .imp  // this field is of type Option[List[Impression]], not just Impression
              .h    // can't solve this because of the previous line
    val w = request.imp.w
    val w = request.site.domain
    

    An Option is a class that lets you work with the concept of a present or non-present value. To You need to use the methods provided by this class. Mostly map, flatMap, filter but there are others such as fold, getOrEsle, orElse or even you can use a for yield or pattern matching.

    The same happens with the List, where you can't access directly to the field of the element without using the methods that lets you traverse the collection and do something with the value contained by the list.

    That being said, not sure if you need to redefine the schema of your payload, or you need to adapt the code to do something with the value received in the endpoint.

    Here you have some examples of code

    bid_request_params.imp match {
      case Some(imps) => // in case the list was sent in the payload and is not null
        for {
          imp <- imps
        } yield imp.h + imp.w // just doing a sum that probably doesn't make sense. Just to show that at this point I have access to the fields and this will return a new List
      case None => // the list was not sent in the payload 
    }
    
    // the following example should do the same of the code above but written in different way
    bid_request_params
      .imp                 // this is an Option
      .map(imps =>         // the method from Option that lets me apply some transformation of the value contained, in this case the List
        imps
          .map(imp =>      // the method from List that lets me apply some transformation of each element of the List, in this case the Impressions
            imp.h + imp.w  // again the non-sense sum of the fields 
          )
      )