How to specify a request parameter as Json type

752 Views Asked by At

I am creating a Finch endpoint which expects a Json.

URL - LogBundles/Long JSON Message/Process

I am using json4s library for Json parsing

How do I specify the body as type json Or how do I pass a Json value between LogBundles and Process?

I cannot do body.as[case class] because I wont be knowing the exact structure of Json. I will be just looking out for a specific key while parsing.

Code

val bundleProcessEndpoint: Endpoint[String] = put("LogBundles" :: body :: "Process" ) { id =>
                 val jsonBody = parse(id)}

ERROR

could not find implicit value for parameter d: io.finch.Decode.Aux[A,CT] [error] val bundleProcessEndpoint: Endpoint[String] = put("LogBundles" :: body :: "Process" ) { id:JsonInput =>

1

There are 1 best solutions below

2
Vladimir Kostyukov On

There are several ways of doing this, although none of them is considered idiomatic for Finch. The more-or-less safe way to accept an arbitrary JSON object within an Endpoint is to drop down to JSON AST API exposed via the JSON library you're using. For json4s it's going to be org.json4s.JsonAST.JValue.

scala> import io.finch._, io.finch.json4s._, org.json4s._

scala> implicit val formats: Formats = DefaultFormats
formats: org.json4s.Formats = org.json4s.DefaultFormats$@5ee387bc

scala> val e = jsonBody[JsonAST.JValue]
e: io.finch.Endpoint[org.json4s.JsonAST.JValue] = body

scala> e(Input.post("/").withBody[Application.Json](Map("foo" -> 1, "bar" -> "baz"))).awaitValueUnsafe()
res2: Option[org.json4s.JsonAST.JValue] = Some(JObject(List((foo,JInt(1)), (bar,JString(baz)))))

This will give you a JsonAST.JValue instance that you'd need to manually manipulate with (I assume there is a pattern-matching API exposed for that).

An alternative (and way more dangerous) solution would be to ask Finch/JSON4S to decode a JSON object as Map[String, Any]. However, this only works if you don't expect your clients sending JSON arrays as top-level entities.

scala> import io.finch._, io.finch.json4s._, org.json4s._

scala> implicit val formats: Formats = DefaultFormats
formats: org.json4s.Formats = org.json4s.DefaultFormats$@5ee387bc

scala> val b = jsonBody[Map[String, Any]]
b: io.finch.Endpoint[Map[String,Any]] = body

scala> b(Input.post("/").withBody[Application.Json](Map("foo" -> 1, "bar" -> "baz"))).awaitValueUnsafe()
res1: Option[Map[String,Any]] = Some(Map(foo -> 1, bar -> baz))