【问题标题】:JSON Schema - One or none of multiple properties. Easier way?JSON Schema - 多个属性中的一个或没有。更简单的方法?
【发布时间】:2018-02-22 03:52:07
【问题描述】:

我正在使用 hl7 FHIR json 模式,其中非常简单且缺少一些我不想为其编写代码的逻辑。有些属性是互斥的,但不是必需的,我正在尝试找到在 json 模式中表示它的最佳方式。

我们以this one为例,具体来说这部分:

"onsetDateTime": {
  "description": "Estimated or actual date or date-time  the condition 
  began, in the opinion of the clinician.",
  "pattern": "-?[0-9]{4}(-(0[1-9]|1[0-2])(-(0[0-9]|[1-2][0-9]|3[0-1])
  (T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\\.[0-9]+)?(Z|(\\+|-)
  ((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)?",
  "type": "string"
},
"_onsetDateTime": {
  "description": "Extensions for onsetDateTime",
  "$ref": "Element.schema.json#/definitions/Element"
},
"onsetAge": {
  "description": "Estimated or actual date or date-time  the condition 
  began, in the opinion of the clinician.",
  "$ref": "Age.schema.json#/definitions/Age"
},
"onsetPeriod": {
  "description": "Estimated or actual date or date-time  the condition 
  began, in the opinion of the clinician.",
  "$ref": "Period.schema.json#/definitions/Period"
},
"onsetRange": {
  "description": "Estimated or actual date or date-time  the condition 
  began, in the opinion of the clinician.",
  "$ref": "Range.schema.json#/definitions/Range"
},
"onsetString": {
  "description": "Estimated or actual date or date-time  the condition 
  began, in the opinion of the clinician.",
  "type": "string"
},
"_onsetString": {
  "description": "Extensions for onsetString",
  "$ref": "Element.schema.json#/definitions/Element"
}
  • 不能同时有两个 onset* 属性。所以如果有onsetDateTime,那么就不可能有onsetAge、onsetPeriod、onsetRange、onsetString
  • 只有 onsetString 可以有 _onsetString,只有 onsetDateTime 可以有 _onsetDateTime,但它们都不需要存在
  • 不需要发病*

我能够完成它,但它既乏味又漫长。我不介意这样做,但我想知道是否有更简单的方法。

这是我得到的:

"dependencies":
  "onsetDateTime": {
    "allOf": [
      {
        "not": {"required": ["onsetAge"]}
      },
      {
        "not": {"required": ["onsetPeriod"]}
      },
      {
        "not": {"required": ["onsetRange"]}
      },
      {
        "not": {"required": ["onsetString"]}
      },
      {
        "not": {"required": ["_onsetString"]}
      }
    ]
  },
  "onsetAge": {
    "allOf": [
      {
        "not": {"required": ["_onsetDateTime"]}
      },
      {
        "not": {"required": ["onsetPeriod"]}
      },
      {
        "not": {"required": ["onsetRange"]}
      },
      {
        "not": {"required": ["onsetString"]}
      },
      {
        "not": {"required": ["_onsetString"]}
      }
    ]
  },
  "onsetPeriod": {
    "allOf": [
      {
        "not": {"required": ["_onsetDateTime"]}
      },
      {
        "not": {"required": ["onsetRange"]}
      },
      {
        "not": {"required": ["onsetString"]}
      },
      {
        "not": {"required": ["_onsetString"]}
      }
    ]
  },
  "onsetRange": {
    "allOf": [
      {
        "not": {"required": ["_onsetDateTime"]}
      },
      {
        "not": {"required": ["onsetString"]}
      },
      {
        "not": {"required": ["_onsetString"]}
      }
    ]
  },
  "onsetString": {
    "allOf": [
      {
        "not": {"required": ["_onsetDateTime"]}
      }
    ]
  }
}

有什么想法/解决方案吗?在同一个 json 模式中还有另一个这样的模式,所以依赖关系很长,其他模式有更多的属性可供选择。

谢谢!

【问题讨论】:

  • 有很多方法可以解决这个问题,而且都很复杂。你想达到什么目的?完全验证?
  • @GrahameGrieve 是的,完全验证。我正在为每个资源编写大量测试,因此一次性验证 json 结构会很有帮助。最终可能不值得,但只是想获得最好的方法。
  • 我们没有在 json 方案验证上投入太多,因为它非常有限。我们专注于软件验证库,因为它们走得更远。这并不是说我们不会进一步改进架构
  • 我明白了。不过,我正在用 Python 做一个项目,但我不记得看到过 Python 的验证库。

标签: json jsonschema hl7-fhir


【解决方案1】:

很高兴您发现 FHIR Json 模式很有用!

所以,有几件事……您指向的 Json Schema 不是最新的。它们作为 STU3 的一部分在官方网站上;但最新版本来自 2018 年 1 月的工作组,有大量更新和修复,并使用新的一体化格式来解决循环依赖和其他 $ref 问题。通过以下任一链接获取最新信息。

http://build.fhir.org/fhir.schema.json.zip
https://www.npmjs.com/package/fhir-schemas

不过,您是对的……还有改进的余地。而且,令人高兴的是,它现在是一个活跃的开发领域,这些改进很有可能被纳入官方模式。

所以,看看你提出的问题,我们也许能够从oneOf 和可能的anyOf 中得到一些更好的结果。根据 Condition 资源的最新版本,我会尝试以下方法:

{
  "Condition": {
    "description": "A clinical condition, problem, diagnosis...",
    "properties": {
      "resourceType": {
          "const": "Condition"
      },
      "id": {...},
      "meta": {...},
      "oneOf": [
        "onsetDateTime": {...},
        "_onsetDateTime": {...},
        "onsetAge": {...},
        "onsetPeriod": {...},
        "onsetRange": {...},
        "onsetString": {...},
        "_onsetString": {...}
      ]
    }
  }
}

这可能就像将onset* 字段包装在oneOf 数组中一样简单。

【讨论】:

  • 我不知道有一组新模式。我相信我尝试了 oneOf 方法,但我会在新版本上尝试一下,看看我是否可以让它工作。谢谢!
  • 这个解决方案的问题是 oneOf 期望其中一个是真的,所以我不能没有任何 oneOf 属性的 json。而且我认为语法不正确。
【解决方案2】:

您可以尝试使用"dependencies""not""required" 来解决这个问题。例如,要表达“如果存在 onsetAge,则不应存在 onsetPeriod 和 onsetRange”,您可以执行以下操作:

{
  "dependencies": {
    "onsetAge": {
      "allOf": [
        {"not": {"required": ["onsetPeriod"]}},
        {"not": {"required": ["onsetRange"]}}
      ]
    }
  }
}

(我没有测试,只是一个想法)

【讨论】:

  • 我在上面的例子中就是这样。
猜你喜欢
  • 2020-07-11
  • 1970-01-01
  • 1970-01-01
  • 2019-12-13
  • 1970-01-01
  • 1970-01-01
  • 2021-11-08
  • 1970-01-01
  • 2020-03-19
相关资源
最近更新 更多