0

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 =>

Prateek Mane
  • 111
  • 1
  • 9

1 Answers1

1

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))
Vladimir Kostyukov
  • 2,492
  • 3
  • 21
  • 30
  • Hello Vladimir, Correct me if I am wrong. But my question was how to consume the Json payload from the endpoint for a PUT request sent by the user. WithBody Overrides the Payload sent by the user. – Prateek Mane Mar 08 '17 at 06:51
  • The last lines in those two examples are just to demonstrate what the endpoint returns on a given input. You don't need it in your application. I encourage you to have a look at our [user guide](https://finagle.github.io/finch/user-guide.html) that should help you to clear up all the confusion. – Vladimir Kostyukov Mar 08 '17 at 07:39