So i am trying to create a custom decoder for a JSON string to be converted into a domain object. I am using Scala/Circe to walk through the JSON and create the object. I am unable to get this to run. I am sure i am not clear on how to walk through the JSON. Can someone advise please ?
This is the JSON in question ,
{
"args": {},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-US,en;q=0.9",
"Host": "httpbin.org",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36"
},
"origin": "61.16.136.118, 61.16.136.118",
"url": "https://httpbin.org/get"
}
Here is what my code looks like,
import com.softwaremill.sttp._
import com.softwaremill.sttp.circe._
import io.circe._, io.circe.parser._
case class Headers(Accept: String, Accept_Encoding: String, Accept_Language: String, Host: String, Upgrade_Insecure_Requests: String, User_Agent: String)
case class RootInterface(args: String, headers: Headers, origin: String, url: String)
object SttpClientGetPost extends App {
implicit val backend = HttpURLConnectionBackend()
implicit val rootDecoder: Decoder[RootInterface] =
(hCursor: HCursor) => {
val tcursor = hCursor.downField("headers")
val argsCursor = hCursor.downField("args")
for{
args <- for{
testString <- argsCursor.get[String]("args")
}yield testString
headers <- for {
Accept <- tcursor.downField("Accept").as[String]
Accept_Encoding <- tcursor.downField("Accept-Encoding").as[String]
Accept_Language <- tcursor.downField("Accept-Language").as[String]
Host <- tcursor.downField("Host").as[String]
Upgrade_Insecure_Requests <- tcursor.downField("Upgrade-Insecure-Requests").as[String]
User_Agent <- tcursor.downField("User-Agent").as[String]
} yield Headers(Accept, Accept_Encoding, Accept_Language, Host, Upgrade_Insecure_Requests, User_Agent)
origin <- hCursor.downField("Origin").as[String]
url <- hCursor.downField("url").as[String]
} yield RootInterface("", headers, origin, url)
}
val secondRequest = sttp //.headers(("userId", USER_ID),("password","testpassword"))
.get(uri"http://httpbin.org/get")
secondRequest.send().body match {
case Left(fail) => System.out.println("The Get request was unsuccessful. " + fail)
case Right(rawJSONResponse) =>
parser.decode(rawJSONResponse) match {
case Left(fail) => System.out.println("The JSON response could not be parsed by Circe. " + fail)
case Right(rootInterfaceObject) =>
System.out.println("Origin :" + rootInterfaceObject.origin)
}
}
}
Update : I am trying with this to no avail now,
case class Headers(Accept: String, Accept_Encoding: String, Accept_Language: String, Host: String, Upgrade_Insecure_Requests: String, User_Agent: String)
case class RootInterface(args: String, headers: Headers, origin: String, url: String)
val doc = """{
"args": {},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-US,en;q=0.9",
"Host": "httpbin.org",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36"
},
"origin": "61.16.136.118, 61.16.136.118",
"url": "https://httpbin.org/get"
}"""
implicit val decodeHeaders: Decoder[Headers] = Decoder.forProduct6(
"Accept",
"Accept-Encoding",
"Accept-Language",
"Host",
"Upgrade-Insecure-Requests",
"User-Agent"
)(Headers(_, _, _, _, _, _))
implicit val decodeRootInterface: Decoder[RootInterface] = Decoder.forProduct4(
"args",
"headers",
"origin",
"url"
)(RootInterface(_, _, _, _))
val t = decode[RootInterface](doc)
I am still getting a decoding failure. It looks like its because of the args
field.