问题描述
我正在尝试将JSON反序列化为DTO类,该类的属性类型为nestedDto[]
。不幸的是,数组内部的对象反序列化为数组,而不是nestedDto
的实例。
我的DTO类如下:
class TestDto
{
/**
* @var nestedDto
*/
public nestedDto $c;
/**
* @var nestedDto[] $cs
*/
public array $cs;
}
class nestedDto
{
public string $s;
}
function main() {
$serializer = new JsonSerializer();
$json = '{"c":{"s":"nested"},"cs":[{"s":"nested1"},{"s":"nested2"}]}';
$dto = $serializer->fromJSON(TestDto::class,$json);
echo '<pre>' . print_r($dto,true) . '</pre>';
$response = $serializer->toJSON($dto);
exit($response);
}
您可以看到属性c
是适当的nestedDto
,但是在cs
数组中,我们有两个数组,而不是两个nestedDto
实例。
TestDto Object
(
[c] => nestedDto Object
(
[s] => nested
)
[cs] => Array
(
[0] => Array
(
[s] => nested1
)
[1] => Array
(
[s] => nested2
)
)
)
这是JsonSerializer
类的代码,该类是Symfony序列化程序的包装器:
final class JsonSerializer
{
private Serializer $serializer;
private ValidatorInterface $validator;
/**
* JsonSerializer constructor.
*/
public function __construct()
{
$encoders = [new JsonEncoder()];
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$normalizers = [
new Objectnormalizer($classMetadataFactory,NULL,new ReflectionExtractor()),new ArrayDenormalizer(),new DateTimenormalizer(),];
$this->serializer = new Serializer($normalizers,$encoders);
$this->validator = Validation::createValidatorBuilder()->enableAnnotationMapping()->getValidator();
}
/**
* Create a DTO class from json. Will also auto-validate the DTO.
* @param $classFQN string The class FQN,e.g. \App\Something\CreateQuoteDTO::class
* @param $json string The string containing JSON we will use for the DTO.
* @return array|mixed|object An instance of the $class.
*/
public function fromJSON( string $classFQN,string $json )
{
$instance = $this->serializer->deserialize($json,$classFQN,'json');
$errors = $this->validator->validate($instance);
if (count($errors) > 0) {
throw new \RuntimeException('Invalid DTO.');
}
return $instance;
}
/**
* Convert a class instance to JSON string
* @param $object
* @return string
*/
public function toJSON( $object ) : string
{
return $this->serializer->serialize($object,'json');
}
}
我已经阅读了关于Stack Overflow的所有类似问题,但是找不到我的代码中缺少的内容。我的猜测是在JsonSerializer中使用的规范化器中未正确连接某些东西,但是花了很长时间后,我才发现线索。
这是您可以在其中运行它的沙箱中的所有代码:phpsandbox.io
以防万一,对于这个示例,我需要在composer中使用的软件包是:
"symfony/serializer-pack": "*","symfony/validator": "*","doctrine/annotations": "*","doctrine/cache": "*",
解决方法
我已经分叉了您的链接,并且在序列化后,我在$ cs变量中得到了NestedDto数组。有效的解决方案:https://phpsandbox.io/n/fragrant-field-wgn5