Assuming the following json payload
val json = """{
"choices" : [
{
"name" : "A"
},
{
"name" : "B"
},
{
"name" : "C"
},
{
"name" : "D"
}
],
"domain" : "Quizz",
"level" : "Test",
"mandatory": true
}"""
How do I transform it to
val json = """{
"value":"B",
"domain" : "Quizz",
"level" : "Test",
}"""
where the "B" is randomly selected from the available choices ?
This is what I have got so far :
val cursor = parse(json).getOrElse(Json.Null).cursor
for{
noMandatory<- cursor.downField("mandatory").flatMap(_.delete).map(_.top)
withEmptyValue = noMandatory.deepMerge(Json.obj("value"->Json.Null))
}yield withEmptyValue
This drops the unused "mandatory" field and inserts an empty "value" field. Getting a random value from the array and placing it in "value" escapes me though.
-- edit
I have tried using hcursor which makes the above clearer (to me anyway)
val cursor = parse(json).getOrElse(Json.Null).hcursor
val noMandatory = cursor.downField("mandatory").delete
val withEmptyValue = noMandatory.withFocus(_.deepMerge(Json.obj("value"->Json.Null)))
(I am using circe 0.5.1 in the above examples)
Do not mix side effects with pure code. So I didn't solve your randomisation problem.
Second, I'd recommend not removing the 'choices' field to keep things simple. Remove that field later when you feel like it.
Third, separate the getting and transformation stages for simplicity. Here you can use a case class to do most of the work.
I'm sure this might not be the idiomatic Circe solution but it's good Scala:
import io.circe._, io.circe.generic.auto._, io.circe.parser._, io.circe.syntax._
object ChooserApp extends App {
val input =
"""{
"choices" : [
{
"name" : "A"
},
{
"name" : "B"
},
{
"name" : "C"
},
{
"name" : "D"
}
],
"domain" : "Quizz",
"level" : "Test",
"mandatory": true
}"""
val expected =
"""{
"choices" : [
{
"name" : "A"
},
{
"name" : "B"
},
{
"name" : "C"
},
{
"name" : "D"
}
],
"value":"B",
"domain" : "Quizz",
"level" : "Test",
"mandatory": true
}"""
case class ForJson(j: Json) {
def choices: List[String] = {
j.asObject
.toList
.flatMap(_ ("choices"))
.flatMap(_.asArray)
.flatten
.flatMap(_.asObject)
.flatMap(_ ("name"))
.flatMap(_.asString)
}
def chosen(a: String): Json = {
j.asObject
.map(_.add("value", Json.fromString(a)))
.map(Json.fromJsonObject)
.getOrElse(j)
}
}
val expectedList = List("A", "B", "C", "D")
val gotList = ForJson(parse(input).toOption.get).choices
assert(gotList == expectedList, s"Expected $expectedList, got $gotList")
val expectedJson = parse(expected).toOption.get
val gotJson = ForJson(parse(input).toOption.get).chosen("B")
assert(gotJson == expectedJson, s"Expected $expectedJson, got $gotJson")
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With