假设下面的json有效负载
val json = """{
"choices" : [
{
"name" : "A"
},
{
"name" : "B"
},
{
"name" : "C"
},
{
"name" : "D"
}
],
"domain" : "Quizz",
"level" : "Test",
"mandatory": true
}"""如何将其转换为
val json = """{
"value":"B",
"domain" : "Quizz",
"level" : "Test",
}"""其中"B“是从可用选项中随机选择的?
这是我到目前为止所得到的:
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这将删除未使用的“强制”字段,并插入一个空的“值”字段。不过,从数组中获取一个随机值并将其放入" value“中是我所不能理解的。
--编辑
我试过使用hcursor,它使上面的内容更清晰(至少对我来说)
val cursor = parse(json).getOrElse(Json.Null).hcursor
val noMandatory = cursor.downField("mandatory").delete
val withEmptyValue = noMandatory.withFocus(_.deepMerge(Json.obj("value"->Json.Null)))(我在上面的例子中使用了circe 0.5.1 )
发布于 2016-09-26 22:47:37
不要在纯代码中混用副作用。所以我没有解决你的随机化问题。
其次,为了简单起见,我建议不要删除“选项”字段。以后当您想要删除该字段时,请将其删除。
第三,为了简单起见,将获取和转换阶段分开。在这里,您可以使用case类来完成大部分工作。
我确信这可能不是惯用的Circe解决方案,但它是很好的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")
}发布于 2016-09-27 03:38:14
在深入研究了api之后,我得出了以下结论:
// a couple utilities
def renameKey(srcKey:String,target:String )(obj:JsonObject):Json= {
obj("name").fold(obj)(value => obj.add("value", value).remove("name")).asJson
}
def safeDropKeys(json:Json)(keys:String*):Json=
json.withObject(obj=>keys.foldLeft(obj)((acc, s)=>acc.remove(s)).asJson)我根据@scala-william建议分离的随机提取器:
def extractRandomChip(cursor: HCursor): Xor[DecodingFailure, Json] = {
val choice = cursor.get[Array[Json]]("choices").map { choices =>
val x = util.Random.nextInt(choices.length)
choices(x).withObject(renameKey("name", "value"))
}
choice
}然后将它们粘合在一起:
val json = for {
initial <- parse(s)
value <- extractRandomChip(initial.hcursor)
cleanedUp = safeDropKeys(initial)("mandatory","choices")
} yield cleanedUp.deepMerge(value)
json.map(_.toString).toOption根据我在@wheaties answer上的评论,我将对这两个选项进行基准测试,并接受最快选项的结果。
发布于 2018-03-22 13:22:40
我的2分钱
@ for{
j <- parser.parse(json).toOption
jObj <- j.asObject
jChoices <- jObj("choices")
choices <- jChoices.as[Seq[Map[String,Json]]].toOption
v <- choices(Random.nextInt(choices.size)).get("name")
} yield {
jObj.add("value", v ) .remove("choices")
}
res58: Option[io.circe.JsonObject] = Some(object[domain -> "Quizz",level -> "Test",mandatory -> true,value -> "C"])https://stackoverflow.com/questions/39702899
复制相似问题