Denormalize IRI to resource #5128
Replies: 11 comments
-
What exception? I think that you should set the groups accordingly and avoid to denormalize the group in that case. |
Beta Was this translation helpful? Give feedback.
-
The exception was UPDATE: when I execute PUT request on User resource, this exception doesn't happen because there is |
Beta Was this translation helpful? Give feedback.
-
Okay so this is definitely due too constructor arguments. Would it be possible to add default values to the constructor parameters to see if it fixes the bug? Indeed, when doing the IRI denormalization, the group name isn't needed. @Nek- did you experience this as well? |
Beta Was this translation helpful? Give feedback.
-
I just had made test repository to reproduce the issue https://github.com/ghettovoice/api-platform/tree/issue-2123. Full stack trace: {
"@context": "/contexts/Error",
"@type": "hydra:Error",
"hydra:title": "An error occurred",
"hydra:description": "Cannot create an instance of App\\Entity\\Group from serialized data because its constructor requires parameter \"name\" to be present.",
"trace": [
{
"namespace": "",
"short_class": "",
"class": "",
"type": "",
"function": "",
"file": "/srv/api/vendor/symfony/serializer/Normalizer/AbstractNormalizer.php",
"line": 389,
"args": []
},
{
"namespace": "Symfony\\Component\\Serializer\\Normalizer",
"short_class": "AbstractNormalizer",
"class": "Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer",
"type": "->",
"function": "instantiateObject",
"file": "/srv/api/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php",
"line": 143,
"args": [
[
"array",
[
[
"string",
"/groups/1"
]
]
],
[
"string",
"App\\Entity\\Group"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
],
"api_denormalize": [
"boolean",
true
],
"cache_key": [
"string",
"3109355309ab720c2fd4470e519cd894"
]
}
],
[
"object",
"ReflectionClass"
],
[
"array",
[
[
"string",
"username"
],
[
"string",
"group"
]
]
],
[
"string",
"json"
]
]
},
{
"namespace": "Symfony\\Component\\Serializer\\Normalizer",
"short_class": "AbstractObjectNormalizer",
"class": "Symfony\\Component\\Serializer\\Normalizer\\AbstractObjectNormalizer",
"type": "->",
"function": "instantiateObject",
"file": "/srv/api/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php",
"line": 244,
"args": [
[
"array",
[
[
"string",
"/groups/1"
]
]
],
[
"string",
"App\\Entity\\Group"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
],
"api_denormalize": [
"boolean",
true
],
"cache_key": [
"string",
"3109355309ab720c2fd4470e519cd894"
]
}
],
[
"object",
"ReflectionClass"
],
[
"array",
[
[
"string",
"username"
],
[
"string",
"group"
]
]
],
[
"string",
"json"
]
]
},
{
"namespace": "Symfony\\Component\\Serializer\\Normalizer",
"short_class": "AbstractObjectNormalizer",
"class": "Symfony\\Component\\Serializer\\Normalizer\\AbstractObjectNormalizer",
"type": "->",
"function": "denormalize",
"file": "/srv/api/vendor/api-platform/core/src/Serializer/AbstractItemNormalizer.php",
"line": 128,
"args": [
[
"string",
"/groups/1"
],
[
"string",
"App\\Entity\\Group"
],
[
"string",
"json"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
],
"api_denormalize": [
"boolean",
true
],
"cache_key": [
"string",
"3109355309ab720c2fd4470e519cd894"
]
}
]
]
},
{
"namespace": "ApiPlatform\\Core\\Serializer",
"short_class": "AbstractItemNormalizer",
"class": "ApiPlatform\\Core\\Serializer\\AbstractItemNormalizer",
"type": "->",
"function": "denormalize",
"file": "/srv/api/vendor/api-platform/core/src/Serializer/ItemNormalizer.php",
"line": 43,
"args": [
[
"string",
"/groups/1"
],
[
"string",
"App\\Entity\\Group"
],
[
"string",
"json"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
],
"api_denormalize": [
"boolean",
true
],
"cache_key": [
"string",
"3109355309ab720c2fd4470e519cd894"
]
}
]
]
},
{
"namespace": "ApiPlatform\\Core\\Serializer",
"short_class": "ItemNormalizer",
"class": "ApiPlatform\\Core\\Serializer\\ItemNormalizer",
"type": "->",
"function": "denormalize",
"file": "/srv/api/vendor/symfony/serializer/Serializer.php",
"line": 177,
"args": [
[
"string",
"/groups/1"
],
[
"string",
"App\\Entity\\Group"
],
[
"string",
"json"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
],
"api_denormalize": [
"boolean",
true
],
"cache_key": [
"string",
"3109355309ab720c2fd4470e519cd894"
]
}
]
]
},
{
"namespace": "Symfony\\Component\\Serializer",
"short_class": "Serializer",
"class": "Symfony\\Component\\Serializer\\Serializer",
"type": "->",
"function": "denormalize",
"file": "/srv/api/vendor/symfony/serializer/Normalizer/AbstractNormalizer.php",
"line": 370,
"args": [
[
"string",
"/groups/1"
],
[
"string",
"App\\Entity\\Group"
],
[
"string",
"json"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
],
"api_denormalize": [
"boolean",
true
],
"cache_key": [
"string",
"3109355309ab720c2fd4470e519cd894"
]
}
]
]
},
{
"namespace": "Symfony\\Component\\Serializer\\Normalizer",
"short_class": "AbstractNormalizer",
"class": "Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer",
"type": "->",
"function": "instantiateObject",
"file": "/srv/api/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php",
"line": 143,
"args": [
[
"array",
{
"group": [
"string",
"/groups/1"
]
}
],
[
"string",
"App\\Entity\\User"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
],
"api_denormalize": [
"boolean",
true
],
"cache_key": [
"string",
"3109355309ab720c2fd4470e519cd894"
]
}
],
[
"object",
"ReflectionClass"
],
[
"array",
[
[
"string",
"username"
],
[
"string",
"group"
]
]
],
[
"string",
"json"
]
]
},
{
"namespace": "Symfony\\Component\\Serializer\\Normalizer",
"short_class": "AbstractObjectNormalizer",
"class": "Symfony\\Component\\Serializer\\Normalizer\\AbstractObjectNormalizer",
"type": "->",
"function": "instantiateObject",
"file": "/srv/api/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php",
"line": 244,
"args": [
[
"array",
{
"group": [
"string",
"/groups/1"
]
}
],
[
"string",
"App\\Entity\\User"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
],
"api_denormalize": [
"boolean",
true
],
"cache_key": [
"string",
"3109355309ab720c2fd4470e519cd894"
]
}
],
[
"object",
"ReflectionClass"
],
[
"array",
[
[
"string",
"username"
],
[
"string",
"group"
]
]
],
[
"string",
"json"
]
]
},
{
"namespace": "Symfony\\Component\\Serializer\\Normalizer",
"short_class": "AbstractObjectNormalizer",
"class": "Symfony\\Component\\Serializer\\Normalizer\\AbstractObjectNormalizer",
"type": "->",
"function": "denormalize",
"file": "/srv/api/vendor/api-platform/core/src/Serializer/AbstractItemNormalizer.php",
"line": 128,
"args": [
[
"array",
{
"username": [
"string",
"test"
],
"group": [
"string",
"/groups/1"
]
}
],
[
"string",
"App\\Entity\\User"
],
[
"string",
"json"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
],
"api_denormalize": [
"boolean",
true
],
"cache_key": [
"string",
"3109355309ab720c2fd4470e519cd894"
]
}
]
]
},
{
"namespace": "ApiPlatform\\Core\\Serializer",
"short_class": "AbstractItemNormalizer",
"class": "ApiPlatform\\Core\\Serializer\\AbstractItemNormalizer",
"type": "->",
"function": "denormalize",
"file": "/srv/api/vendor/api-platform/core/src/Serializer/ItemNormalizer.php",
"line": 43,
"args": [
[
"array",
{
"username": [
"string",
"test"
],
"group": [
"string",
"/groups/1"
]
}
],
[
"string",
"App\\Entity\\User"
],
[
"string",
"json"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
],
"api_denormalize": [
"boolean",
true
]
}
]
]
},
{
"namespace": "ApiPlatform\\Core\\Serializer",
"short_class": "ItemNormalizer",
"class": "ApiPlatform\\Core\\Serializer\\ItemNormalizer",
"type": "->",
"function": "denormalize",
"file": "/srv/api/vendor/symfony/serializer/Serializer.php",
"line": 177,
"args": [
[
"array",
{
"username": [
"string",
"test"
],
"group": [
"string",
"/groups/1"
]
}
],
[
"string",
"App\\Entity\\User"
],
[
"string",
"json"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
]
}
]
]
},
{
"namespace": "Symfony\\Component\\Serializer",
"short_class": "Serializer",
"class": "Symfony\\Component\\Serializer\\Serializer",
"type": "->",
"function": "denormalize",
"file": "/srv/api/vendor/symfony/serializer/Serializer.php",
"line": 128,
"args": [
[
"array",
{
"username": [
"string",
"test"
],
"group": [
"string",
"/groups/1"
]
}
],
[
"string",
"App\\Entity\\User"
],
[
"string",
"json"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
]
}
]
]
},
{
"namespace": "Symfony\\Component\\Serializer",
"short_class": "Serializer",
"class": "Symfony\\Component\\Serializer\\Serializer",
"type": "->",
"function": "deserialize",
"file": "/srv/api/vendor/api-platform/core/src/EventListener/DeserializeListener.php",
"line": 95,
"args": [
[
"array",
{
"username": [
"string",
"test"
],
"group": [
"string",
"/groups/1"
]
}
],
[
"string",
"App\\Entity\\User"
],
[
"string",
"json"
],
[
"array",
{
"collection_operation_name": [
"string",
"post"
],
"operation_type": [
"string",
"collection"
],
"api_allow_update": [
"boolean",
false
],
"resource_class": [
"string",
"App\\Entity\\User"
],
"request_uri": [
"string",
"/users"
],
"uri": [
"string",
"http://localhost:8080/users"
]
}
]
]
},
{
"namespace": "ApiPlatform\\Core\\EventListener",
"short_class": "DeserializeListener",
"class": "ApiPlatform\\Core\\EventListener\\DeserializeListener",
"type": "->",
"function": "onKernelRequest",
"file": null,
"line": null,
"args": [
[
"object",
"Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent"
],
[
"string",
"kernel.request"
],
[
"object",
"Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher"
]
]
},
{
"namespace": "",
"short_class": "",
"class": "",
"type": "",
"function": "call_user_func",
"file": "/srv/api/vendor/symfony/event-dispatcher/Debug/WrappedListener.php",
"line": 104,
"args": [
[
"array",
[
[
"object",
"ApiPlatform\\Core\\EventListener\\DeserializeListener"
],
[
"string",
"onKernelRequest"
]
]
],
[
"object",
"Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent"
],
[
"string",
"kernel.request"
],
[
"object",
"Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher"
]
]
},
{
"namespace": "Symfony\\Component\\EventDispatcher\\Debug",
"short_class": "WrappedListener",
"class": "Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener",
"type": "->",
"function": "__invoke",
"file": "/srv/api/vendor/symfony/event-dispatcher/EventDispatcher.php",
"line": 212,
"args": [
[
"object",
"Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent"
],
[
"string",
"kernel.request"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\EventDispatcher"
]
]
},
{
"namespace": "Symfony\\Component\\EventDispatcher",
"short_class": "EventDispatcher",
"class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
"type": "->",
"function": "doDispatch",
"file": "/srv/api/vendor/symfony/event-dispatcher/EventDispatcher.php",
"line": 44,
"args": [
[
"array",
[
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
],
[
"object",
"Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener"
]
]
],
[
"string",
"kernel.request"
],
[
"object",
"Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent"
]
]
},
{
"namespace": "Symfony\\Component\\EventDispatcher",
"short_class": "EventDispatcher",
"class": "Symfony\\Component\\EventDispatcher\\EventDispatcher",
"type": "->",
"function": "dispatch",
"file": "/srv/api/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php",
"line": 141,
"args": [
[
"string",
"kernel.request"
],
[
"object",
"Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent"
]
]
},
{
"namespace": "Symfony\\Component\\EventDispatcher\\Debug",
"short_class": "TraceableEventDispatcher",
"class": "Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher",
"type": "->",
"function": "dispatch",
"file": "/srv/api/vendor/symfony/http-kernel/HttpKernel.php",
"line": 125,
"args": [
[
"string",
"kernel.request"
],
[
"object",
"Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent"
]
]
},
{
"namespace": "Symfony\\Component\\HttpKernel",
"short_class": "HttpKernel",
"class": "Symfony\\Component\\HttpKernel\\HttpKernel",
"type": "->",
"function": "handleRaw",
"file": "/srv/api/vendor/symfony/http-kernel/HttpKernel.php",
"line": 66,
"args": [
[
"object",
"Symfony\\Component\\HttpFoundation\\Request"
],
[
"integer",
1
]
]
},
{
"namespace": "Symfony\\Component\\HttpKernel",
"short_class": "HttpKernel",
"class": "Symfony\\Component\\HttpKernel\\HttpKernel",
"type": "->",
"function": "handle",
"file": "/srv/api/vendor/symfony/http-kernel/Kernel.php",
"line": 188,
"args": [
[
"object",
"Symfony\\Component\\HttpFoundation\\Request"
],
[
"integer",
1
],
[
"boolean",
true
]
]
},
{
"namespace": "Symfony\\Component\\HttpKernel",
"short_class": "Kernel",
"class": "Symfony\\Component\\HttpKernel\\Kernel",
"type": "->",
"function": "handle",
"file": "/srv/api/public/index.php",
"line": 37,
"args": [
[
"object",
"Symfony\\Component\\HttpFoundation\\Request"
]
]
}
]
}
If make |
Beta Was this translation helpful? Give feedback.
-
It's one of the reasons I dislike the denormalization via constructor and why I wasn't in favor of implementing this :p. We don't retrieve the name because we already know the group |
Beta Was this translation helpful? Give feedback.
-
It's just was unexpected for me that fetching by IRI works in update request (that is mentioned in docs) and doesn't works in create requests. Anyway I rewrite this part using DTOs and custom persister/data provider. |
Beta Was this translation helpful? Give feedback.
-
@ghettovoice your work around looks great! and honestly seems like it would be like the only proper way to handle this? I can't imagine adding this check comes with any major performance issues for denormalization in general. Because regardless if you are setting via constructor or by public property, the string value needs to be denormalized. |
Beta Was this translation helpful? Give feedback.
-
Hi @ragboyjr , |
Beta Was this translation helpful? Give feedback.
-
@ghettovoice Thanks, i also needed to add a compiler pass to update the API platform item normalizer to use the custom one. |
Beta Was this translation helpful? Give feedback.
-
Is there a better way to do this yet with API Platform? I made a copy+paste gist based on code from @ghettovoice above, for anyone that runs into this issues too https://gist.github.com/VeryStrongFingers/866f755b558b2b4f6d47389c8fd51816 |
Beta Was this translation helpful? Give feedback.
-
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Beta Was this translation helpful? Give feedback.
-
Hi, I noticed that ItemNormalizer doesn't support denormalizing of IRI string. I have an issue, probably related to #2036, with deserializing entity with type hinted constructor. For example if we have User and Group entities which are exposed as API resources:
Sending POST to
/users
request with payload:This leads to exception when symfony AbstractNormalizer trying to denormalize
$group
argument to theGroup
resource from string/groups/123456
. Actually ItemNormalizer is used to denormalize IRI string but it doesn't trying to load resource from IRI converter like it does for array withid
field here .As a workaround currently I'm using extended
ItemNormalizer
I'm using the latest
api-platform/core:2.3
Beta Was this translation helpful? Give feedback.
All reactions