背景
我有一组配置 JSON 文件,如下所示:
{
"version" : 1.0,
"startDate": 1548419535,
"endDate": 1558419535,
"sourceData" : [...] // nested json inside the List.
"destData" : [...] // nested json inside the List.
"extra" : ["business_type"]
}
有几个这样的配置文件。它们是固定的,仅驻留在我的代码目录中。每个配置文件的内部表示由我的案例类
Config
给出:case class Attribute(name: String, mappedTo: String)
case class Data(location: String, mappings:List[Attribute])
case class Config(version: Double, startDate: Long, endDate: Long, sourceData: List[Data],
destData: List[Data], extra: List[String])
我有三个类(class)
Provider
, Parser
和 Validator
.Provider
有一个方法 getConfig(date: Long): Config
.它必须返回满足 startDate <= date <= endDate
的配置(理想情况下应该只存在一个这样的配置,因为 startDate
到 endDate
定义了要返回的配置版本)。 getConfig
调用内部的方法 Parser
叫 parseList(jsonConfigs: List[String]): Try[List[Config]]
.什么 parseList
做的是尝试反序列化列表中的所有配置,每个配置到案例类 Config
的一个实例.即使一个 JSON 无法反序列化 parseList
返回 scala.util.Failure
否则返回 scala.util.Success[List[Config]]
. scala.util.Success[List[Config]]
从上一步返回,getConfig
然后最后调用内部的一个方法 Validator
叫 def validate(List[Config], Date): ValidationResult[Config]
,并返回它的结果。由于我希望累积所有错误,因此我正在使用 Cats Validated用于验证。我什至问了一个关于它正确用法的问题 here . validate
执行以下操作:检查是否正好 一
Config
在列表中,适用于给定的date (
startDate <= date <= endDate
) 然后对该 Config
执行一些验证(否则返回 invalidNel
)。我对 Config
执行了一些基本验证例如检查各种列表和字符串是否为非空等。我还执行一些语义验证,例如检查字段 extra
中的每个字符串存在于 mappings
每个source/dest Data
等题
Cats Validated
的目的是什么?只是为了收集所有错误(并且在遇到第一个验证错误时不会快速失败)。但是当我到达时validate
方法我已经在 parseList
中做了某种验证方法。也就是说,我已经在parseList
中验证过了我的 JSON 结构符合我的案例类 Config
.但是我的parseList
不会像我的 validate
那样累积错误方法。因此,如果我的 json 结构和我的案例类之间存在许多不兼容性 Config
在场我只会了解第一个。但我想一次性了解他们。 require
会变得更糟条款如 nonEmpty
仅在案例类内部(它们将在案例类的构建时被调用,即在解析自身时),例如case class Data(location: String, mappings: List[Attribute]) {
require(location.nonEmpty)
require(mappings.nonEmpty)
}
所以我无法正确地在解析和验证功能之间划清界限。
Cats Validated
(我知道它 here ,非常适合 Cats invalidNel
)。我以为我会先解析 JSON 到 play-json 的 JSON AST JsValue
, 在 JsValue
之间执行结构兼容验证和我的 Config
使用 play-jsons validate
方法(它会累积错误)。如果它很好读 Config
案例类来自 JsValue
并使用 Cats 执行我上面给出的示例的后续验证。 (startDate, endDate)
附上给定的日期。所以如果我按照我上面提到的解决方案,我已经推送了 List[JsValue]
的转换至 List[Config]
到验证阶段。现在如果每个 JsValue
在列表中成功反序列化为 Config
例如,我可以选择适用的一个,对其执行更多验证并返回结果。但如果有些 JsValue
无法反序列化我该怎么办?我应该返回他们的错误吗?看起来不直观。这里的问题是我需要解析所有配置以查看哪个配置适用于给定日期。这让我更难区分解析和验证阶段。 如何在我的场景中解析和验证配置之间划清界限?我是否更改了维护版本的方式(版本从开始日期到结束日期都有效)?
PS:总的来说,我是一个非常新手的程序员。如果我的问题很奇怪,请原谅我。我自己从没想过我会在学习 Scala 的同时花这么多时间在验证上。
最佳答案
Checks if exactly one Config in the List matches
如果所描述的行为是要求,则格式错误的 JSON 文件是一个验证错误。您可以将 Try[List[]] 返回类型更改为 List[Try[]] 并在必要时将其与 Validated 集成。该文档可能有使用 std lib 类的便捷方法。
如果我们可以取第一个匹配的,那就是早午餐:进行相同的更改,只需在查找配置时在列表中找到匹配的第一个即可。
关于scala - 在使用 scala 的版本化配置的情况下,如何将解析与验证分开?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54366991/