Rest 向序列化对象添加自定义属性

Rest 向序列化对象添加自定义属性,rest,symfony,fosrestbundle,jmsserializerbundle,jms-serializer,Rest,Symfony,Fosrestbundle,Jmsserializerbundle,Jms Serializer,我正在为web服务开发RESTful API。我需要公开一些不属于实体本身的属性 例如,我有一个Pizza实体对象,它有自己的size和name属性。我用FOSRestBundle和JMSSerializer以JSON格式输出它。我已经为这个实体设置了属性注释,以便通过序列化组公开所需的属性,它工作得很好 但是我需要添加一些不属于实体本身的属性。例如,我希望我的pizza具有属性:isFresh,该属性由一些PizzaService::isFresh(pizza$pizza)服务确定。我该怎么做

我正在为web服务开发RESTful API。我需要公开一些不属于实体本身的属性

例如,我有一个
Pizza
实体对象,它有自己的
size
name
属性。我用FOSRestBundle和JMSSerializer以JSON格式输出它。我已经为这个实体设置了属性注释,以便通过序列化组公开所需的属性,它工作得很好

但是我需要添加一些不属于实体本身的属性。例如,我希望我的
pizza
具有属性:
isFresh
,该属性由一些
PizzaService::isFresh(pizza$pizza)
服务确定。我该怎么做

  • 我是否应该向序列化过程注入一些额外的逻辑(如果是的话,如何注入)
  • 我是否应该创建一个包装器实体,其中包含我希望从原始实体公开的属性以及其他外部属性
  • 在序列化之前,我是否应该将属性
    isFresh
    添加到原始
    Pizza
    实体并填充到控制器中
  • 我是否应该独立于实体数据返回其他数据(例如在同级JSON属性中)

换句话说:围绕这个问题的最佳实践是什么?你能举个例子吗?谢谢。

我想您可以通过VirtualProperty注释来实现这一点:

/**
 * @JMS\VirtualProperty
 * @return boolean
 */
public function isFresh (){
     ...
}
编辑:另一个带有访问者注释的解决方案

/** @Accessor(getter="getIsFresh",setter="setIsFresh") */
private $isFresh;

// ...
public function getIsFresh()
{
    return $this->isFresh;
}

public function setIsFresh($isFresh)
{
    $this->isFresh= $isFresh;
}
在控制器中,调用setIsFresh方法


(请参阅)

我决定创建自己的类来序列化实体

下面是一个例子:

class PizzaSerializer implements ObjectSerializerInterface
{
    /** @var PizzaService */
    protected $pizzaService;

    /**
     * @param PizzaService $pizzaService
     */
    public function __construct(PizzaService $pizzaService)
    {
        $this->pizzaService = $pizzaService;
    }

    /**
     * @param Pizza $pizza
     * @return array
     */
    public function serialize(Pizza $pizza)
    {
        return [
            'id'      => $pizza->getId(),
            'size'    => $pizza->getSize(),
            'name'    => $pizza->getName(),
            'isFresh' => $this->pizzaService->isFresh($pizza),
        ];
    }
}
您只需将DC配置为将
PizzaService
注入到对象序列化程序中,然后从控制器像这样调用它:

$pizza = getPizzaFromSomewhere();

$pizzaSerializer = $this->get('serializer.pizza');

return $pizzaSerializer->serialize($pizza);

对象序列化程序将返回一个数组,该数组可以通过使用真正的序列化程序(如
JMS serializer
)轻松转换为JSON、XML、YAML或任何其他格式
FOSRestBundle
将自动执行此操作,如果您将其配置为这样。

此问题也与此虚拟财产依赖于服务有关,似乎这只是答案的一部分。也许你也可以设想一种方法来实现它?是的,你是对的。我认为“我应该在序列化之前将属性isFresh添加到原始Pizza实体并填充到控制器中吗?”是更好的解决方案。为此,我添加了另一种访问器注释方式嘿,谢谢你的回答。为什么你认为这种方法更好?其他方法的缺点是什么?您是否在实践中实施了此设计?