둘 중 하나 또는 둘 중 하나(다른 두 필드 중 하나)를 모두 필요로 하지 않는 방법은 무엇입니까?
JSON에 다음 중 하나가 포함되어 있는지 검증하는 JSON 스키마를 작성하는데 문제가 있습니다.
- 한 필드만
- 다른 필드만
- (기타 2개의 필드 중 하나)
하지만 그 배수가 존재할 때는 일치하지 않습니다.
제 경우엔, 특히 다음 중 하나를 원합니다.
copyAll
fileNames
matchesFiles
및/또는doesntMatchFiles
검증할 수 있지만, 그 이상의 것이 있는 경우는 받아들이고 싶지 않습니다.
지금까지 알아낸 내용은 다음과 같습니다.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": [ "unrelatedA" ],
"properties": {
"unrelatedA": {
"type": "string"
},
"fileNames": {
"type": "array"
},
"copyAll": {
"type": "boolean"
},
"matchesFiles": {
"type": "array"
},
"doesntMatchFiles": {
"type": "array"
}
},
"oneOf": [
{"required": ["copyAll"], "not":{"required":["matchesFiles"]}, "not":{"required":["doesntMatchFiles"]}, "not":{"required":["fileNames"]}},
{"required": ["fileNames"], "not":{"required":["matchesFiles"]}, "not":{"required":["doesntMatchFiles"]}, "not":{"required":["copyAll"]}},
{"anyOf": [
{"required": ["matchesFiles"], "not":{"required":["copyAll"]}, "not":{"required":["fileNames"]}},
{"required": ["doesntMatchFiles"], "not":{"required":["copyAll"]}, "not":{"required":["fileNames"]}}]}
]
} ;
이건 내가 원하는 것보다 더 잘 어울린다.다음 항목에 모두 일치시키십시오.
{"copyAll": true, "unrelatedA":"xxx"}
{"fileNames": ["aab", "cab"], "unrelatedA":"xxx"}
{"matchesFiles": ["a*"], "unrelatedA":"xxx"}
{"doesntMatchFiles": ["a*"], "unrelatedA":"xxx"}
{"matchesFiles": ["a*"], "doesntMatchFiles": ["*b"], "unrelatedA":"xxx"}
일치하지 않음:
{"copyAll": true, "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"fileNames": ["a"], "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"copyAll": true, "doesntMatchFiles": ["*b"], "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"fileNames": ["a"], "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"unrelatedA":"xxx"}
내가 놓치고 있는 게 분명해 - 그게 뭔지 알고 싶어
문제는 "not" 의미론입니다."not required"는 "disclused forgidd"를 의미하지 않습니다즉, 스키마를 검증하기 위해 추가할 필요가 없습니다.
그러나 "One Of"를 사용하면 사양을 더 쉽게 충족할 수 있습니다.이는 "이러한 스키마 중 하나만 검증할 수 있다"는 것을 의미합니다.다음 스키마는 해결하려는 속성 전환을 달성합니다.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": [
"unrelatedA"
],
"properties": {
"unrelatedA": {
"type": "string"
},
"fileNames": {
"type": "array"
},
"copyAll": {
"type": "boolean"
},
"matchesFiles": {
"type": "array"
},
"doesntMatchFiles": {
"type": "array"
}
},
"oneOf": [
{
"required": [
"copyAll"
]
},
{
"required": [
"fileNames"
]
},
{
"anyOf": [
{
"required": [
"matchesFiles"
]
},
{
"required": [
"doesntMatchFiles"
]
}
]
}
]
}
값이 다음과 같은 속성인 경우null
없는 거나 마찬가지니까 이런 게 어울릴 것 같아요. commonProp
다음 중 하나만 제공해야 합니다.x
또는y
제공할 수 있습니다.
유사한 오류 메시지가 몇 개 표시될 수 있습니다.
{
$schema: 'http://json-schema.org/draft-07/schema#',
type: 'object',
required: ['commonProp'],
oneOf: [
{
properties: {
x: { type: 'number' },
commonProp: { type: 'number' },
y: {
type: 'null',
errorMessage: "should ONLY include either ('x') or ('y') keys. Not a mix.",
},
},
additionalProperties: { not: true, errorMessage: 'remove additional property ${0#}' },
},
{
properties: {
y: { type: 'number' },
commonProp: { type: 'number' },
x: {
type: 'null',
errorMessage: "should ONLY include either ('x') or ('y') keys. Not a mix.",
},
},
additionalProperties: { not: true, errorMessage: 'remove additional property ${0#}' },
},
],
}
const model = { x: 0, y: 0, commonProp: 0 };
// ⛔️ ⛔️ ⛔️ ⛔️ ⛔️ ⛔️
// Model>y should ONLY include either ('x') or ('y') keys. Not a mix.
// Model>x should ONLY include either ('x') or ('y') keys. Not a mix.
const model = { x: 0, y: null, commonProp: 0 };
// ✅ ✅ ✅ ✅ ✅ ✅
const model = { x: 0 };
// ⛔️ ⛔️ ⛔️ ⛔️ ⛔️ ⛔️
// Model must have required property 'commonProp'
코멘트에서 @Tomeamis가 지적한 바와 같이 불필요한 조합은 json 스키마에서 "금지"를 의미합니다.다만, 「not」키워드는 중복하지 말아 주세요(이유는 잘 모르겠습니다).대신, 당신은 해야 합니다.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": [ "unrelatedA" ],
"properties": {
"unrelatedA": {
"type": "string"
},
"fileNames": {
"type": "array"
},
"copyAll": {
"type": "boolean"
},
"matchesFiles": {
"type": "array"
},
"doesntMatchFiles": {
"type": "array"
}
},
"oneOf": [
{
"required": [
"copyAll"
],
"not": {
"anyOf": [
{"required":["matchesFiles"]},
{"required":["doesntMatchFiles"]},
{"required":["fileNames"]}
]
}
},
{
"required": [
"fileNames"
],
"not": {
"anyOf": [
{"required":["matchesFiles"]},
{"required":["doesntMatchFiles"]},
{"required":["copyAll"]}
]
}
},
{
"anyOf": [
{
"required": ["matchesFiles"],
"not": {
"anyOf": [
{"required":["fileNames"]},
{"required":["copyAll"]}
]
}
},
{
"required": ["doesntMatchFiles"],
"not": {
"anyOf": [
{"required":["fileNames"]},
{"required":["copyAll"]}
]
}
}]
}
]
}
자세한 내용은 이쪽
재산의 존재를 금지하기 위해 다음과 같이 할 수도 있다.
{
"properties": {
"x": false
}
}
이 회답에 기재된 바와 같이
파티에는 조금 늦었지만, 스키마 내에서 기능하고 재사용 가능한 솔루션을 오늘 구현했습니다.
컨텍스트의 경우 이름으로 입력해야 하는 필드가 여러 개 있었지만 값이 비어 있거나 다른 조건에 따라 존재해야 할 수 있습니다.
재사용 가능한 TypeScript 메서드는 다음과 같습니다.
// SchemaLogic.ts
import { Schema } from "jsonschema";
/**
* A required string property with a minimum length of 0.
*/
export const StringValue = { type: "string", required: true, minLength: 0 };
/**
* A required string property with a minimum length of 1.
*/
export const NonEmptyStringValue = { type: "string", required: true, minLength: 1 };
/**
* Provides the option to submit a value for one of the two
* property names provided. If one of the properties is
* submitted with a truthy string value, then the other will
* not be required to have a value. If neither are submitted
* with a truthy value, then both will return an error
* message saying that the minimum length requirement has
* not been met.
*
* **NOTE:**
* 1. this only works with string properties that are
* not restricted to a certain set of values or a
* regex-validated format
* 1. this must be used inside an `allOf` array
*
* @param propertyNames the names of the properties
* @returns a {@link Schema} that creates a conditional
* requirement condition between the two fields
*/
export const eitherOr = (propertyNames: [string, string]): Schema => {
return {
if: { properties: { [propertyNames[0]]: NonEmptyStringValue } },
then: { properties: { [propertyNames[1]]: StringValue } },
else: {
if: { properties: { [propertyNames[1]]: NonEmptyStringValue } },
then: { properties: { [propertyNames[0]]: StringValue } },
else: {
properties: {
[propertyNames[0]]: NonEmptyStringValue,
[propertyNames[1]]: NonEmptyStringValue,
},
},
},
};
};
그리고 여기 가장 기본적인 사용 방법의 예가 있습니다.여기에는 다음이 필요합니다.
xCode
그리고.xDescription
존재해야 하지만 하나의 값만 있으면 됩니다.yCode
그리고.yDescription
존재해야 하지만 하나의 값만 있으면 됩니다.
import { eitherOr } from "./SchemaLogic";
const schema: Schema = {
allOf: [eitherOr(["xCode", "xDescription"]), eitherOr(["yCode", "yDescription"])],
};
이러한 필드를 조건부로 필요로 하는 경우는, 다음과 같은 것을 사용할 수 있습니다.
const schema: Schema = {
properties: {
type: {
type: ["string"],
enum: ["one", "two", "three"],
required: true,
},
},
if: {
// if the 'type' property is either "one" or "two"...
properties: { type: { oneOf: [{ const: "one" }, { const: "two" }] } },
},
then: {
// ...require values
allOf: [eitherOr(["xCode", "xDescription"]), eitherOr(["yCode", "yDescription"])],
},
};
주의:
에서 '하다'를 사용하는
additionalProperties: false
【속성】션에 속성을 추가하여 정의해야 합니다.그렇지 않으면 필드가 존재해야 하는 동시에 추가 필드이기 때문에 허용되지 않습니다.
이것이 도움이 되기를 바랍니다!
이 답변은 JSON 스키마와는 관련이 없기 때문에 조금 빗나갔지만, 이 문제를 해결하기 위한 다른 관점이나 일반적인 json 검증을 가져올 수 있습니다.
요점은 결과적으로 필요한 것을 선언적으로 정확하게 표현하는 것입니다. 즉, 유일한 필드입니다.다음 json 스키마를 고려합니다.
JsonElement json =
new Gson().toJsonTree(
Map.of(
"first_field", "vasya",
"second_field", false,
"third_field", 777,
"unrelated", "Rinse"
)
);
둘 중 .first_field
,second_field
, , , , 입니다.third_field
네 번째 필드는 중요하지 않습니다.대응하는 검증 오브젝트는 다음과 같습니다.
Result<SomeTestStructure> result =
new UnnamedBlocOfNameds<SomeTestStructure>(
List.of(
new OneOf(
"global",
new ErrorStub("Only one of the fields must be present"),
new AsString(
new Required(
new IndexedValue("first_field", json)
)
),
new AsBoolean(
new Required(
new IndexedValue("second_field", json)
)
),
new AsInteger(
new Required(
new IndexedValue("third_field", json)
)
)
),
new AsString(
new IndexedValue("unrelated", json)
)
),
SomeTestStructure.class
)
.result();
먼저 이름 있는 블록으로 구성된 이름 없는 블록을 선언한 다음 세 가지 요소 중 하나의 성공 가능한 요소가 필요하다고 말합니다.그리고 마지막으로, 당신은 성공이 무엇을 의미하는지 선언합니다.이 경우 성공하는 것은 단순히 존재하는 것이다.한 경우, .SomeTestStructure
클래스가 생성됩니다.
assertTrue(result.isSuccessful());
assertEquals(
new SomeTestStructure(777, "Rinse").thirdField(),
result.value().raw().thirdField()
);
이 접근법과 이를 구현하는 라이브러리에 대한 자세한 내용은 빠른 시작 항목을 참조하십시오.
언급URL : https://stackoverflow.com/questions/24023536/how-do-i-require-one-field-or-another-or-one-of-two-others-but-not-all-of-them
'programing' 카테고리의 다른 글
woocommerce에 커스텀 배송료를 추가하는 방법은? (0) | 2023.03.15 |
---|---|
Chrome 업데이트로 인해 Ajax/Angular Network 렌더링 및 로드 속도가 느려졌습니다. (0) | 2023.03.15 |
스프링 부트:단위시험에서 액화효소로 시험데이터를 설정하는 방법 (0) | 2023.03.15 |
Android에서 HTTP Client를 사용하여 JSON에서 POST 요청을 보내는 방법은 무엇입니까? (0) | 2023.03.15 |
Elastic Search를 사용하여 여러 필드에서 검색 (0) | 2023.03.15 |