symfony 如何使用自定义StateProvider设置JsonLd @context?

rqmkfv5c  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(112)

为了解释我的问题,我设置了一个非常简单的ApiResource,它使用自定义状态提供程序。

#[ApiResource(
    types: 'https://schema.org/UpdateAction',
    provider: TransitionStateProvider::class,
)]
class Transition
{
    #[ApiProperty(
        identifier: true,
        types: ['https://schema.org/identifier'],
    )]
    public int $id;
}

字符串
我的州供应商:

class TransitionStateProvider implements ProviderInterface
{
    public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
    {
        $transition = new Transition();
        $transition->id = 1;
        
        return $transition;
    }
}


当我发送一个get请求时,@context、@id、@types并没有按照我想要的那样设置。我得到:

{
    "@context": {
        "@vocab": "https://localhost/docs.jsonld#",
        "hydra": "http://www.w3.org/ns/hydra/core#"
    },
    "@type": "Transition",
    "@id": "/.well-known/genid/66dae3d5fb3332ca13ee",
    "id": 1
}


我想要的是:

{
    "@context": "/contexts/Transition",
    "@id": "/transitions/1",
    "@type": "https://schema.org/UpdateAction",
    "id": 1
}


它与我的其他资源一起工作,但它们使用stateOptions链接到一个教义实体。这个Transition资源不是。
我尝试在ApiProperty中设置identifier:true,我尝试使用uriTemplateurivariableshydraContext,但没有成功。
我配置错了什么?

eaf3rand

eaf3rand1#

您可以尝试创建一个custom normalizer来修改序列化过程,并确保@context@id@type按照您的需要进行设置。

namespace App\Serializer;

use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class TransitionNormalizer implements ContextAwareNormalizerInterface
{
    private $decorated;

    public function __construct(NormalizerInterface $decorated)
    {
        $this->decorated = $decorated;
    }

    public function normalize($object, string $format = null, array $context = [])
    {
        $data = $this->decorated->normalize($object, $format, $context);
        $data['@context'] = '/contexts/Transition';
        $data['@id'] = '/transitions/' . $object->id;
        $data['@type'] = 'https://schema.org/UpdateAction';

        return $data;
    }

    public function supportsNormalization($data, string $format = null, array $context = []): bool
    {
        return $data instanceof Transition;
    }
}

字符串
将自定义规范器定义为服务,将tag it定义为serializer.normalizer。这将确保它在Symfony Serializer component中注册。

# config/services.yaml
services:
    App\Serializer\TransitionNormalizer:
        decorates: 'serializer.normalizer.object'
        tags: ['serializer.normalizer']


的数据
并更新Transition类上的ApiResourceannotation以利用自定义规范化器。

#[ApiResource(
    types: 'https://schema.org/UpdateAction',
    provider: TransitionStateProvider::class,
    normalizationContext: ['groups' => ['transition']]
)]
class Transition
{
    #[ApiProperty(
        identifier: true,
        types: ['https://schema.org/identifier'],
    )]
    public int $id;
}


你得到的工作流程:

+---------------+     +----------------------+     +-----------------------+     +-------------------+
| API Resource  |     | Custom Normalizer    |     |   Service Definition  |     | Desired JSON-LD   |
| Transition    | --> | TransitionNormalizer | --> | serializer.normalizer | --> |   @context Setup  |
+---------------+     +----------------------+     +-----------------------+     +-------------------+


你更新的代码与上面的建议:

namespace App\Serializer;

use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class TransitionNormalizer implements ContextAwareNormalizerInterface
{
    private $decorated;

    public function __construct(NormalizerInterface $decorated)
    {
        $this->decorated = $decorated;
    }

    public function normalize($object, string $format = null, array $context = [])
    {
        $data = $this->decorated->normalize($object, $format, $context);
        $data['@context'] = '/contexts/Transition';
        $data['@id'] = '/transitions/' . $object->id;
        $data['@type'] = 'https://schema.org/UpdateAction';

        return $data;
    }

    public function supportsNormalization($data, string $format = null, array $context = []): bool
    {
        return $data instanceof Transition;
    }
}

// config/services.yaml
services:
    App\Serializer\TransitionNormalizer:
        decorates: 'serializer.normalizer.object'
        tags: ['serializer.normalizer']

// Your ApiResource and Provider remains the same
#[ApiResource(
    types: 'https://schema.org/UpdateAction',
    provider: TransitionStateProvider::class,
    normalizationContext: ['groups' => ['transition']]
)]
class Transition
{
    #[ApiProperty(
        identifier: true,
        types: ['https://schema.org/identifier'],
    )]
    public int $id;
}

class TransitionStateProvider implements ProviderInterface
{
    public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
    {
        $transition = new Transition();
        $transition->id = 1;
        
        return $transition;
    }
}

相关问题