我正在尝试使用Api Platform捆绑软件在使用Symfony 4.4的嵌入式mongodb文档上运行反规范化器(数据输入)。对于标准化(数据输出),这可以按预期工作,但对于非标准化过程,则不会对嵌入数据触发任何操作,仅对父数据触发。
如果这是它的工作方式,那么我可能需要将非规范化逻辑转移到父级中。也许我只是做错了什么。我要完成的工作是在包含已弃用字段的入站请求上引发异常。解析注释并扫描属性的类按预期工作,仅确定将其插入哪里,我希望嵌入式文档上的非规范化过程可以工作。
这是我的services.yaml:
'App\Serializer\InvestmentNormalizer':
arguments: [ '@security.authorization_checker' ]
tags:
- { name: 'serializer.normalizer', priority: 64 }
'App\Serializer\InvestmentDenormalizer':
tags:
- { name: 'serializer.denormalizer', priority: 64 }
'App\Serializer\ProjectNormalizer':
tags:
- { name: 'serializer.normalizer', priority: 64 }
'App\Serializer\ProjectDenormalizer':
tags:
- { name: 'serializer.denormalizer', priority: 64 }
然后是我的反规范化器类,它永远不会执行:
class ProjectDenormalizer implements DenormalizerInterface
{
private const ALREADY_CALLED = 'PROJECT_DENORMALIZER_ALREADY_CALLED';
public function denormalize($data, $class, $format = null, array $context = [])
{
$context[self::ALREADY_CALLED] = true;
return $this->removeDeprecatedFields($data);
}
public function supportsDenormalization($data, $type, $format = null)
{
if (isset($context[self::ALREADY_CALLED])) {
return false;
}
return $type == get_class(new Project());
}
private function removeDeprecatedFields(array $normalizedData) : array
{
$apiPropertyReader = new AnnotationReader(Project::class, ApiProperty::class);
$deprecatedProperties = $apiPropertyReader->readAllHavingAttribute('deprecationReason');
$errors = [];
foreach (array_keys($deprecatedProperties) as $deprecatedPropertyName) {
if (!isset($normalizedData[$deprecatedPropertyName])) {
continue;
}
$errors[] = $deprecatedPropertyName . ' has been deprecated';
}
if (!empty($errors)) {
throw new DeprecatedFieldException(implode('. ', $errors));
}
return $normalizedData;
}
}
[如果您查看文档,会发现序列化程序组件没有任何serializer.denormalizer
服务,因此,自动发现不会检测到您的班级。 Symfony Service Tags
您需要遵循并实现规范化程序,该规范化程序在单个类中同时实现规范化程序和去规范化程序逻辑,并将其注册为规范化程序Normalizer & Encoder usages
然后,名称约定听起来很混乱,但是您的规范化器会通过将序列化逻辑标记为适当的方法来对它们进行适当的调用,从而将其标准化为(C0),将规范化为(C0),并将其标准化为(C0)。
API平台本身提供了有关两者如何工作的示例:DenormalizerInterface
这是您在api平台上装饰Normalizer的方法:
NormalizerInfterface
或者您可以按照symfony的方式注册此规范化器:
decorating-a-serializer-and-adding-extra-data
实施:
services:
'App\Serializer\ApiNormalizer':
decorates: 'api_platform.jsonld.normalizer.item'
arguments: [ '@App\Serializer\ApiNormalizer.inner' ]
您可以折射逻辑并为每个实体创建Normalizer类。无论您使用什么数据库,对于PHP和Symfony来说,都是对象。
在此处浏览完整的文档以了解其实现方式:services:
get_set_method_normalizer:
class: Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer
tags: [serializer.normalizer]