英文:
Symfony - How to specify root to deserialize json array to object using JMS\Serializer
问题
# Json Response
{
"data": {
"totalCount": 3,
"version": "v1"
}
}
<?php
# The object to deserialize into
namespace App;
use JMS\Serializer\Annotation as Serializer;
class ExampleResponse
{
/**
* @var int
*
* @Serializer\Type("integer")
* @Serializer\SerializedName("totalCount")
*/
protected $totalCount;
/**
* @var string
*
* @Serializer\Type("string")
* @Serializer\SerializedName("version")
*/
protected $version;
}
# Deserialization call
# I have to decode the json into an array and then json encode the internals of "data"
$this->serializer->deserialize(
json_encode(
json_decode(
$json,
true,
512,
JSON_THROW_ON_ERROR
)['data'],
JSON_THROW_ON_ERROR
),
App\ExampleResponse::class,
'json'
)
英文:
I receive json responses from a certain server to API requests in this format:
{
"data": {
#result here
}
}
But I need to do deserialization of the result itself inside "data". I could not find in the documentation how to specify the json deserialization root
Example:
# Json Response
{
"data": {
"totalCount": 3,
"version": "v1"
}
}
<?php
# The object to deserialize into
namespace App;
use JMS\Serializer\Annotation as Serializer;
class ExampleResponse
{
/**
* @var int
*
* @Serializer\Type("integer")
* @Serializer\SerializedName("totalCount")
*/
protected $totalCount;
/**
* @var string
*
* @Serializer\Type("string")
* @Serializer\SerializedName("version")
*/
protected $version;
}
# Deserialization call
# I have to decode the json into an array and then json encode the internals of "data"
$this->serializer->deserialize(
json_encode(
json_decode(
$json,
true,
512,
JSON_THROW_ON_ERROR
)['data'],
JSON_THROW_ON_ERROR
),
App\ExampleResponse::class,
'json'
)
Is there a better solution?
答案1
得分: 0
可以,但有点繁琐。
最简单的方法是使用 json_decode
并使用 fromArray
方法反序列化对象:
$response = json_decode($json, true);
$this->serializer->fromArray($response['data'], App\ExampleResponse::class)
另一种解决方案是使用订阅者监听 pre_deserialize
事件:
class JsonDeserializationSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [[
'event' => 'serializer.pre_deserialize',
'method' => 'onPreDeSerialize',
'format' => 'json', // optional format
'priority' => 0, // optional priority
]];
}
public function onPreDeSerialize(PreDeserializeEvent $event): void
{
$data = $event->getData();
if (is_array($data) && array_key_exists('data', $data)) {
$event->setData($data['data']);
}
}
}
还需要配置监听器:
$serializer = SerializerBuilder::create()->configureListeners(
fn (EventDispatcher $e) => $e->addSubscriber(new JsonDeserializationSubscriber())
)->build();
$serializer->deserialize($json, App\ExampleResponse::class, 'json');
英文:
It is possible but a little bit cumbersome.
The easiest approach is to use json_decode
and deserialize the object with the fromArray
method:
$response = json_decode($json, true);
$this->serializer->fromArray($response['data'], App\ExampleResponse::class)
The other solution is to use a subscriber to listen on the pre_deserialize
event:
class JsonDeserializationSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [[
'event' => 'serializer.pre_deserialize',
'method' => 'onPreDeSerialize',
'format' => 'json', // optional format
'priority' => 0, // optional priority
]];
}
public function onPreDeSerialize(PreDeserializeEvent $event): void
{
$data = $event->getData();
if (is_array($data) && array_key_exists('data', $data)) {
$event->setData($data['data']);
}
}
And you also need to configure the listener:
$serializer = SerializerBuilder::create()->configureListeners(
fn (EventDispatcher $e) => $e->addSubscriber(new JsonDeserializationSubscriber())
)->build();
$serializer->deserialize($json, App\ExampleResponse::class, 'json');
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论