簡體   English   中英

FOSRestBundle:在請求中詢問的屬性的部分響應

[英]FOSRestBundle: partial response in function of attributes asked in the request

上下文

我發現了許多關於使用FOSRest進行部分API響應的問題,所有答案都基於JMS序列化程序選項(exlude,include,groups等)。 它工作正常,但我試圖實現一些不那么“靜態”的東西。

假設我有一個具有以下屬性的用戶: id username firstname lastname age sex

我使用端點GET /users/{id}和以下方法檢索此用戶:

/**
 * @View
 *
 * GET /users/{id}
 * @param integer $user (uses ParamConverter)
 */
public function getUserAction(User $user) {
    return $user;
}

該方法返回用戶的所有屬性。

現在我想允許這樣的東西: GET /users/{id}?attributes=id,username,sex

我是否錯過了FOSRestBUndle,JMSserializer或SensioFrameworkExtraBundle的功能來自動實現它? 請求中的注釋,方法,關鍵字或其他內容?

否則,實現它的最佳方法是什么?

我想做類似的事情:

/**
 * @View
 * @QueryParam(name="attributes")
 *
 * GET /users/{id}
 *
 * @param integer $user (uses ParamConverter)
 */
public function getUserAction(User $user, $attributes) {
    $groups = $attributes ? explode(",", $attributes) : array("Default");

    $view = $this->view($user, 200)
        ->setSerializationContext(SerializationContext::create()->setGroups($groups));

    return $this->handleView($view);
}

並為每個屬性創建一個組:

use JMS\Serializer\Annotation\Groups;

class User {

    /** @Groups({"id"}) */
    protected $id;

    /** @Groups({"username"}) */
    protected $username;

    /** @Groups({"firstname"}) */
    protected $firstname;

    //etc
}

我的實現基於Igor的答案

ExlusionStrategy:

use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Context;

class FieldsExclusionStrategy implements ExclusionStrategyInterface {
    private $fields = array();

    public function __construct(array $fields) {
        $this->fields = $fields;
    }

    public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext) {
        return false;
    }

    public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext) {
        if (empty($this->fields)) {
            return false;
        }

        if (in_array($property->name, $this->fields)) {
            return false;
        }

        return true;
    }
}

控制器:

/**
 * @View
 * @QueryParam(name="fields")
 *
 * GET /users/{id}
 *
 * @param integer $user (uses ParamConverter)
 */
public function getUserAction(User $user, $fields) {
    $context = new SerializationContext();
    $context->addExclusionStrategy(new FieldsExclusionStrategy($fields ? explode(',', $fields) : array()));

    return $this->handleView($this->view($user)->setSerializationContext($context));
}

終點:

GET /users/{id}?fields=id,username,sex

正如您所示,您可以通過群組進行此操作。 也許更優雅的解決方案是實現您自己的ExclusionStrategy @Groups和其他也是ExclusionStrategyInterface的實現。

所以,比如你說你的策略是SelectFieldsStrategy 實現后,您可以非常輕松地將其添加到序列化上下文中:

$context = new SerializationContext();
$context->addExclusionStrategy(new SelectFieldsStrategy(['id', 'name', 'someotherfield']));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM