paramters unmarshalling with .as[T] and .as(Unmarshaller)

60 views
Skip to first unread message

Conor Reedy

unread,
May 26, 2016, 4:02:46 PM5/26/16
to spray.io User List
using custom unmarshallers / json formats in the parameters directive for spray-routing is throwing the error 
  
  "too many arguments for method parameters: (pdm: spray.routing.directives.ParamDefMagnet)pdm.Out"

I've tried to use both a custom Unmarshaller and a Json Formatter both yeild the same error.

Here is the code...(nothing special but LocalDate is a joda.time class)

parameters('accountIds, 'startDate.as[LocalDate], 'endDate.as[LocalDate]) {
        (ids, sDate, eDate) => compete ("aw shucks") }


Here is the test is checking both the as[T] and as(Unmarshaller) syntax

  "JsonString" should {
    "convert application/json to LocalDate" in {
      val subject = HttpEntity(MediaTypes.`application/json`, "2010-10-10")
      val num     = HttpEntity(MediaTypes.`application/json`, "2")

      subject.as(LocalDateUnmarshaller) should be (Right(new LocalDate("2010-10-10")))
      subject.as[LocalDate]             should be (Right(new LocalDate("2010-10-10")))
    }
  }

any idea on what I could be doing wrong here?

Thanks,
Conor

Age Mooij

unread,
May 26, 2016, 4:31:42 PM5/26/16
to spray...@googlegroups.com
Hi Connor

I know it can be pretty confusing to keep all the type classes straight in Spray, especially when the magnet pattern is then wrapped around it. 

Spray has two types of deserializer type classes. One for entire entities and one for raw Strings or byte arrays. The Unmarshaller trait used when deserializing entire entities builds on top of a lower-level layer called Deserializer, which is the one you need for parameters. You can see the design of this in the package object of the spray.httpx.unmarshalling package:


and the code for Deserializer:


The parameters directive expects something called a FromStringDeserializer, since parameters are encoded as Strings. There are a large number of predefined ones and they are defined here:


If you provide an implicit instance of FromStringDeserializer[LocalDate], your code will magically work. 

Here's the skeleton of one I wrote a long time ago for Joda's DateTime:

import scala.util.control.NonFatal
implicit val stringToDateTimeDeserializer =
  new FromStringDeserializer[DateTime] {
    def apply(in: String) = {
      try {
        Right(stringToDateTime(in))
      } catch {
        case NonFatal(ex) ⇒ Left(MalformedContent(ex.toString, ex))
      }
    }
  }

It will help you solving this type of problem in the future if you read about the Magnet Pattern:


Hope this helps
Age





--
You received this message because you are subscribed to the Google Groups "spray.io User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to spray-user+...@googlegroups.com.
Visit this group at https://groups.google.com/group/spray-user.
To view this discussion on the web visit https://groups.google.com/d/msgid/spray-user/72b00da9-478b-4a8c-9c1d-467c0cf2b613%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Conor Reedy

unread,
May 26, 2016, 7:11:12 PM5/26/16
to spray.io User List
Ah ok.  That makes so much more sense now! Thanks for the help as always.
Reply all
Reply to author
Forward
0 new messages