Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json 强制执行a";至少应存在两个字段中的一个;周而复始_Json_Scala_Circe - Fatal编程技术网

Json 强制执行a";至少应存在两个字段中的一个;周而复始

Json 强制执行a";至少应存在两个字段中的一个;周而复始,json,scala,circe,Json,Scala,Circe,我正在编写一个Circe解析器,其中模式要求至少设置两个字段中的一个。这是非常具体的,而且它似乎不是一种使用CirceAPI轻松实现的方法 让我们调用字段text和html 我已经尝试创建一个类,我们称它为Content,将它作为单个参数添加到通用模型中,如果它的两个字段(文本和html)都没有,则在构造函数中引发一个异常。问题是如何定义解码器,因为如果我这样做 implicit val decodeContent: Decoder[ItemContent] = Decoder.forP

我正在编写一个Circe解析器,其中模式要求至少设置两个字段中的一个。这是非常具体的,而且它似乎不是一种使用CirceAPI轻松实现的方法

让我们调用字段
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你可以从导出的解码器开始,在其结果上添加验证。我已经更新了答案,它起作用了。非常感谢你。你的回答让我对如何使用这个图书馆有了更多的了解。