Skip to content

Commit efb5d76

Browse files
remove incorrect restriction in discriminator
This restriction was also added and then removed from the dialect metaschema, due to a misunderstanding of the spec. see OAI/OpenAPI-Specification#3405 Also handle the ambiguity between named schema and uri-reference in mapping entries.
1 parent e5e4bf7 commit efb5d76

File tree

2 files changed

+16
-32
lines changed

2 files changed

+16
-32
lines changed

lib/JSON/Schema/Modern/Vocabulary/OpenAPI.pm

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ sub _traverse_keyword_discriminator ($self, $schema, $state) {
4848
}
4949
}
5050

51-
$valid = E({ %$state, keyword => undef }, 'missing sibling keyword to discriminator: one of oneOf, anyOf, allOf')
52-
if not grep exists $schema->{$_}, qw(oneOf anyOf allOf);
53-
5451
return 1;
5552
}
5653

@@ -67,15 +64,21 @@ sub _eval_keyword_discriminator ($self, $data, $schema, $state) {
6764
my $discriminator_value = $data->{$discriminator_key};
6865

6966
# if /components/$discriminator_value exists, that schema must validate
70-
my $uri = Mojo::URL->new->fragment(jsonp('', qw(components schemas), $discriminator_value))
67+
my $uri = Mojo::URL->new->fragment(jsonp('/components/schemas', $discriminator_value))
7168
->to_abs($state->{initial_schema_uri});
7269
if (my $component_schema_info = $state->{evaluator}->_fetch_from_uri($uri)) {
7370
$state = { %$state, _schema_path_suffix => 'propertyName' };
7471
}
7572
elsif (exists $schema->{discriminator}{mapping} and exists $schema->{discriminator}{mapping}{$discriminator_value}) {
7673
# use 'mapping' to determine which schema to use.
77-
$uri = Mojo::URL->new($schema->{discriminator}{mapping}{$discriminator_value})
74+
# Note that the spec uses an example that assumes that the mapping value can be appended to
75+
# /components/schemas/, _as well as_ being treated as a uri-reference, but this is ambiguous.
76+
# For now we will handle it by preprending '#/components/schemas' if it is not already a
77+
# fragment-only uri reference.
78+
my $mapping = $schema->{discriminator}{mapping}{$discriminator_value};
79+
$uri = Mojo::URL->new($mapping =~ /^#/ ? $mapping : '#/components/schemas/'.$mapping)
7880
->to_abs($state->{initial_schema_uri});
81+
7982
$state = { %$state, _schema_path_suffix => [ 'mapping', $discriminator_value ] };
8083
}
8184
else {

t/discriminator.t

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -178,19 +178,18 @@ YAML
178178
};
179179

180180
subtest 'discriminator in a parent definition' => sub {
181-
# 8< start of temporary exception-catch
182-
local $TODO = 'requirement of sibling oneOf/anyOf/allOf is not actually in the spec';
183-
184-
my $openapi;
185-
eval {
186-
# >8 end of temporary exception-catch
187-
$openapi = OpenAPI::Modern->new(
181+
my $openapi = OpenAPI::Modern->new(
188182
openapi_uri => '/api',
189183
openapi_schema => $yamlpp->load_string(<<YAML));
190184
$openapi_preamble
191185
description: 'runtime: use discriminator to determine petType'
192186
components:
193187
schemas:
188+
petType:
189+
discriminator:
190+
propertyName: petType
191+
mapping:
192+
dog: Dog
194193
Pet:
195194
type: object
196195
required:
@@ -199,10 +198,6 @@ components:
199198
properties:
200199
petType:
201200
type: string
202-
discriminator:
203-
propertyName: petType
204-
mapping:
205-
dog: Dog
206201
Cat:
207202
allOf:
208203
- \$ref: '#/components/schemas/Pet'
@@ -233,28 +228,14 @@ components:
233228
const: 'null'
234229
YAML
235230

236-
# currently we get:
237-
# instance_location => '',
238-
# keyword_location => '/components/schemas/Pet',
239-
# absolute_keyword_location => '/api#/components/schemas/Pet',
240-
# error => 'missing sibling keyword to discriminator: one of oneOf, anyOf, allOf',
241231
cmp_deeply(
242232
$openapi->evaluator->evaluate(
243-
{ petType => 'Cat', sound => 'meow' },
244-
Mojo::URL->new('/api#/components/schemas/Pet'),
233+
{ petType => 'dog', sound => 'bark' },
234+
Mojo::URL->new('/api#/components/schemas/petType'),
245235
)->TO_JSON,
246236
{ valid => true },
247237
'discriminator can be defined in the base class',
248238
);
249-
250-
# 8< start of temporary exception-catch
251-
};
252-
is(
253-
$@,
254-
'',
255-
'no exception for this use of discriminator',
256-
);
257-
# >8 end of temporary exception-catch
258239
};
259240

260241
done_testing;

0 commit comments

Comments
 (0)