У меня есть файл YAML, который содержит 3 типа полей, определенных в примере ниже. По сути, я хочу иметь возможность разобрать это в общие классы дел, которые представляют эти модели данных.
Этот файл YAML будет меняться очень часто, включая имена полей, значения и т. Д. Единственное, что не изменится, это формат высокого уровня каждого типа данных (см. Ниже)
Самая большая проблема заключается в том, как определить класс case, который принимает несколько типов в одно и то же поле и разбирает YAML на них?
В большинстве примеров в Интернете, похоже, не так много на эту тему, поэтому я попробовал несколько разных вещей, которые в конечном итоге оказались безрезультатными. Похоже, что есть проблема с использованием типов сумм, таких как Either, с библиотекой circe, поскольку я получаю приведенную ниже ошибку. Я также попытался использовать 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:
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)))