【问题标题】:Symfony 5 - How manipulate a serialized object in JSONSymfony 5 - 如何在 JSON 中操作序列化对象
【发布时间】:2021-04-17 06:35:33
【问题描述】:

我想序列化一个对象以获取 JSON。当我序列化这个对象时,我得到了这个:

{
    "id": 1,
    "title": "Title",
    "authors": [
        "/api/authors/1",
        "/api/authors/2"
    ]
}

我想更改 JSON 中的“作者”数据,并将其传递给一个数组。像这个例子:

{
    "id": 1,
    "title": "Title",
    "authors": [
        "id":1,
        "name": "Robert Smith",
        "booksCount":1
        etc etc....
    ]
} 

这是我的实际代码

   $book = $bookRepository->find($id);
    
    
    $authors = array("authors" => $bookRepository->find($id)->getAuthors());

    return $this->json($book, 200, []);

我会用 $authors 中的数组替换“作者”JSON 值。 我怎样才能像我想要的那样操作 JSON 格式?

【问题讨论】:

  • 您目前有任何代码吗?
  • 抱歉,帖子已编辑

标签: arrays json symfony


【解决方案1】:

一种可能性是使用 json_decode 函数。

PHP 文档:json_decodejson_encode

$json_array = json_decode($json, true); // return array

$json_array['authors'] = $bookRepository->find($id)->getAuthors();

$json = json_encode($json_array); //return json

@VirtualProperty()来自JMS serializer的注解@

/**
 * @Serializer\VirtualProperty()
 */

public function getAuthorsCustom()
{
    return ...;
}

【讨论】:

    【解决方案2】:

    首先,您在某些路线的路径中保留对作者的引用很奇怪 @Route("/api/authors/{authorId}").

    建议:

    我会考虑像这样使用 ORM 关系映射:

    Book.php

    /**
     * @ORM\OneToMany(targetEntity="Author", mappedBy="book")
     */
    private $authors;
    

    作者.php

    /**
     * @ORM\ManyToOne(targetEntity="Book", inversedBy="authors")
     * @JoinColumn(name="book_id", referencedColumnName="id")
     */
    private $book;
    

    然后为您服务:

    $book = $entityManager->getRepository(App\Entity\Book::class)->find($id);
    
    return $book;
    

    然后在你的控制器中:

    $book = $yourService->getBook($book_id);
    
    return new JSONResponse($book);
    

    然后在 JavaScript 中:

    let bookJSON = JSON.parse(responseData);
    let authors = bookJSON.authors;
    

    解决办法:

    AuthorRepository.php

    /**
     * @var $ids int[] array of author identifiers
    */
    public function getAuthorsByIds(array $ids)
    {
        // it should return array of author entities
        return $this->createQueryBuilder('author')
            ->select('author')
            ->where("author.id IN (?)")
            ->setParameter($ids)
            ->getQuery()
            ->getResult();
    }
    

    您的控制器

    $book = $bookRepository->find($id);
    $authorIdentificators = $book->getAuthors();
    
    // convert routes to array of ids
    array_walk($authorIdentificators, function(&$route) {
        $route = explode('/', $route)[3];
    });
    
    $authors = $authorRepository->getAuthorsByIds($authorIdentificators);
    
    // notice that your $authors private property is now array of objects (not array of strings(routes))
    $book->setAuthors($authors);
    
    return new JSONResponse($book); // now book JSON should have array of authors
    

    你可以使用这个慢循环来代替存储库方法

    $authors = $book->getAuthors();
    
    // convert routes to array of entity objects:
    array_walk($authors, function(&$route) {
        $route = $authorRepository->find(explode('/', $route)[3]);
    });
    

    【讨论】:

    • 嗨!非常感谢您的帮助。我决定采用第二种解决方案,但我收到此错误“警告:explode() 期望参数 2 是字符串,给定数组”。还有一个问题:为什么在函数中我们给出了两个参数($route 和 $key)但我们只使用了 $route?谢谢!
    • $book->getAuthors();的结果是什么?我希望它是数组或字符串:["/api/authors/1", "/api/authors/2"]。 $route 应该是 $authorIdentificators 数组的每个元素,因此您有一个数组数组,但没有字符串数组。也许 getAuthors() 返回类似这样的内容:['authors' => ["/api/authors/1", "/api/authors/2"]]。我不知道,你告诉我 :) array_walk 的回调可能有 3 个参数,每个参数都是可选的,所以第二个($key)在这里没用(谢谢,我会编辑它)。
    • 我检查了它,然后 $book->getAuthors() 给我发送了一个对象。你建议我怎么做?我转换数组中的对象?
    • 我是这样进行的:我得到了作者,并且通过一个循环,我得到了一个 $authorIdentidicators 的数组,但是,即使在我确认这个变量是一个数组的取消调试之后,我也得到了相同的错误消息“警告:explode() 期望参数 2 是字符串,给定对象”
    • 好吧,但你必须告诉我你的 $authorIdentificators 变量是什么。它必须是一个字符串数组。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    • 2011-05-14
    • 1970-01-01
    • 2018-04-26
    • 2018-12-18
    • 2011-10-25
    • 2017-05-26
    相关资源
    最近更新 更多