`HalResource` does not allow `_embed` data that is based on a `oneOf:` JSONSchema definition
Ocramius opened this issue · comments
Bug Report
Q | A |
---|---|
Version(s) | 2.3.1 |
Summary
This is a union of Foo
and Tab
in a JSONSchema resource:
{
"components": {
"SomeResource": {
"oneOf": [
{"$ref": "#/components/Foo"},
{"$ref": "#/components/Tab"}
]
},
"Foo": {
"type": "object",
"required": ["bar"],
"properties": {
"bar": {"type": "string"}
}
},
"Tab": {
"type": "object",
"required": ["taz"],
"properties": {
"taz": {"type": "string"}
}
}
}
}
In practice, when rendering a list<SomeResource>
, you will get an array of JSON objects with different properties:
[
{"bar": "haha"},
{"taz": "hehe"},
{"bar": "hihi"}
]
Current behavior
HalResource#__construct()
does some pretty aggressive validation of its JSON contents, specifically on $embedded
data:
mezzio-hal/src/HalResource.php
Lines 512 to 529 in 29f006b
This precludes usage of well-documented resources of different types.
How to reproduce
- configure a resource for
class Foo { public string $bar = 'baz'; }
- configure a resource for
class Tab { public string $taz = 'tar'; }
- render a (pseudo-code)
new HalResource(..., ..., [new Foo(), new Tab()])
- it will crash due toFoo
andTab
not sharing same properties
Expected behavior
A HalResource
can be instantiated with $embedded
data of different types:
mezzio-hal/src/HalResource.php
Lines 52 to 54 in 29f006b
Suggested solution
Let's just drop the exception: it was seemingly designed to support developers that have difficulty with keeping their data consistent, but it hinders proper union type design.
My understanding of how embedded collections work in HAL is that a collection (an _embedded
item with an array of resources) is expected to contain resources that are all of the same type.
Interestingly, on reviewing the current draft of the specification, there is no mention of this, which either means this has changed during draft evolution, or my understanding was based on participation in the HAL forums "back in the day".
As such, the only thing that is really required is that each item in the array is a resource (i.e., an object with a Link collection).
Totally willing and ready to review a patch that does this.
@Lucian-Olariu I can send this patch, FWIW 👍
@weierophinney even if they had the same type, a union type is indeed a valid type, heh 😁
Never thought I'd see the day you'd advocate for union types, @Ocramius . 😄