Json 强制执行a";至少应存在两个字段中的一个;周而复始
我正在编写一个Circe解析器,其中模式要求至少设置两个字段中的一个。这是非常具体的,而且它似乎不是一种使用CirceAPI轻松实现的方法 让我们调用字段Json 强制执行a";至少应存在两个字段中的一个;周而复始,json,scala,circe,Json,Scala,Circe,我正在编写一个Circe解析器,其中模式要求至少设置两个字段中的一个。这是非常具体的,而且它似乎不是一种使用CirceAPI轻松实现的方法 让我们调用字段text和html 我已经尝试创建一个类,我们称它为Content,将它作为单个参数添加到通用模型中,如果它的两个字段(文本和html)都没有,则在构造函数中引发一个异常。问题是如何定义解码器,因为如果我这样做 implicit val decodeContent: Decoder[ItemContent] = Decoder.forP
text
和html
我已经尝试创建一个类,我们称它为Content
,将它作为单个参数添加到通用模型中,如果它的两个字段(文本和html)都没有,则在构造函数中引发一个异常。问题是如何定义解码器,因为如果我这样做
implicit val decodeContent: Decoder[ItemContent] =
Decoder.forProduct2("text", "html")(Content.apply)
它要求两个字段都必须存在
我想要的是有一个解码器,如果字段缺失,则将None传递给内容。apply
,但我认为这不是预期的行为
否则,应该有一个完全不同的解决方案,但我想不出一个
谢谢您可以使用解码器#emap
:
import io.circe._, parser._
case class ItemContent(text: Option[String], html: Option[String])
object ItemContent {
implicit val decoder =
Decoder.forProduct2("text", "html")(ItemContent.apply).emap {
case ItemContent(None, None) => Left("Neither text nor html is present")
case x => Right(x)
}
}
assert {
decode[ItemContent]("{}").isLeft &&
decode[ItemContent]("""{"html": "foo"}""") == Right(
ItemContent(None, Some("foo"))) &&
decode[ItemContent]("""{"text": "bar"}""") == Right(
ItemContent(Some("bar"), None)) &&
decode[ItemContent]("""{"html": "foo", "text": "bar"}""") == Right(
ItemContent(Some("bar"), Some("foo")))
}
为了避免指定其他字段,可以使用半自动求导作为基础:
import io.circe._, parser._, io.circe.generic.semiauto._
case class ItemContent(text: Option[String],
html: Option[String],
other: Int,
fields: String)
object ItemContent {
implicit val decoder =
deriveDecoder[ItemContent].emap { ic =>
if (ic.text.isEmpty && ic.html.isEmpty)
Left("Both `text` and `html` are missing")
else Right(ic)
}
}
uuuh,非常有趣,我将尝试它。问题是它试图解析形式为{“content”:{“content\u text”:“abc”}的内容,而我需要在根目录中包含“content\u text”和“content\u html”以及其他字段。通过这种方式,我将其视为嵌套对象,而我的目标是以这种方式解析这两个字段,并正常处理其他字段。整个结构有很多字段,我想用自动派生来解析其他字段。你认为有可能吗?@Chobeat你可以从导出的解码器开始,在其结果上添加验证。我已经更新了答案,它起作用了。非常感谢你。你的回答让我对如何使用这个图书馆有了更多的了解。