【问题标题】:Parsing YAML in Scala/Circe into case classes with union types将 Scala/Circe 中的 YAML 解析为具有联合类型的案例类
【发布时间】:2019-11-02 13:47:10
【问题描述】:

我有一个 YAML 文件,其中包含以下示例中定义的 3 种类型的字段。本质上,我希望能够将其解析为代表这些数据模型的通用案例类。

这个 YAML 文件会经常更改,包括字段名称、值等。唯一不会更改的是每种数据类型的高级格式(见下文)

最大的问题是如何定义一个 case 类,在同一个字段中接受多种类型并将 YAML 解析为它们?

网上的大部分例子似乎都没有关于这个主题的内容,所以我尝试了一些不同的方法,但最终都失败了。当我收到以下错误时,似乎在 circe 库中使用像 Either 这样的 sum 类型存在问题。我还尝试使用 sealed trait 和联合类型无济于事。

示例 YAML 文件:

name: ExampleYamlMapping
version: 0.0
mappings:

  # Single Value Field
  - name: fieldtype1
    value: "singlevalue"

  # Multivalue Fields, Unformatted
  - name: fieldtype2
    value:
      - "multivalue"
      - "multivalue1"

  # Formatted Multivalue field
  - name: fieldtype3
    content_type: "formatted multivalue"
    format: "key1 | key2"
    mappings:
      - name: key1 # Single Value Field
        value: "singlevalue"

      - name: key2 # Multivalue Field, Unformatted
        value:
          - "multivalue1"
          - "multivalue2"

示例案例类:


case class UnorderedField(name: String, value: Either[String, List[String]])

case class OrderedMultiValueField(content_type: String,
                                  format: String,
                                  mappings: List[Either[UnorderedField, OrderedMultiValueField]])

case class ContentMappingExample(
                           name: String,
                           version: String,
                           mappings: List[Either[UnorderedField, OrderedMultiValueField]]
                           )

解析逻辑:

import io.circe.generic.auto._
import io.circe.{Error, Json, ParsingFailure, yaml}

val mappingSource = scala.io.Source.fromFile(mappingFilePath)

mappingData = try mappingSource.mkString finally mappingSource.close()

val mappings: Either[ParsingFailure, Json] = yaml.parser.parse(mappingData)

val contentMapping: ContentMappingExample = mappings
      .leftMap(err => err: Error)
      .flatMap(_.as[ContentMappingExample])
      .valueOr(throw _)

错误信息是:

CNil: DownArray,DownField(mappings)
DecodingFailure(CNil, List(DownArray, DownField(mappings)))

【问题讨论】:

    标签: json scala parsing yaml circe


    【解决方案1】:

    更新:我发现您可以创建代数数据类型 (ADT) 并定义自定义编码器。我遵循以下适用于我的示例:https://circe.github.io/circe/codecs/adt.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-06
      • 2019-03-15
      • 2018-10-22
      • 2014-06-30
      • 2019-01-18
      • 2019-03-13
      • 1970-01-01
      • 2014-06-25
      相关资源
      最近更新 更多