Symfony 5 - 如何在 JSON 中操作序列化对象

Posted

技术标签:

【中文标题】Symfony 5 - 如何在 JSON 中操作序列化对象【英文标题】:Symfony 5 - How manipulate a serialized object in 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 格式?

【问题讨论】:

您目前有任何代码吗? 抱歉,帖子已编辑 【参考方案1】:

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

php 文档:json_decode, json_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 变量是什么。它必须是一个字符串数组。

以上是关于Symfony 5 - 如何在 JSON 中操作序列化对象的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Symfony2 中将 Json 绑定到实体中

如何在 symfony2 控制器中发送 JSON 响应

如何在 symfony 中返回 json 编码格式错误

从 Symfony 中的控制器返回 JSON 数组

最佳实践以及如何在 Symfony2 中找到从 iOS AFNetworking 获取 POST 数据并在 GET 中返回 JSON?

如何正确验证表单中带有 symfony json 约束的学说类型“json”?