如何在 Symfony 5 中创建用于序列化 json 的自定义 Normilizer? [英] How to create a custom Normilizer for serializing json in Symfony 5?
问题描述
我正在用 symfony 创建一个 REST api 并最终想要返回一个自定义的 json.例如隐藏一些字段,从关系对象中获取特定字段(来自外键)等等(底部示例).
I am creating a REST api with symfony and ultimately want to return a custom json. For example hide some fields, get specific fields from the relation object (coming from the foreign key) and so on (example at the bottom).
我有两个具有 ManyToOne
/OneToMany
关系的实体,Product &类别.
I have two entites with a ManyToOne
/OneToMany
relation, Product & Category.
Product.php
:
<?php
namespace App\Entity;
use App\Repository\ProductRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=ProductRepository::class)
*/
class Product
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="text")
*/
private $description;
/**
* @ORM\Column(type="float")
*/
private $price;
/**
* @ORM\Column(type="boolean")
*/
private $available;
/**
* @ORM\ManyToOne(targetEntity=Category::class, inversedBy="products")
* @ORM\JoinColumn(nullable=false)
*/
private $category;
// ...
// Rest of getters & setters
// ...
public function getCategory(): ?Category
{
return $this->category;
}
public function setCategory(?Category $category): self
{
$this->category = $category;
return $this;
}
Category.php
:
<?php
namespace App\Entity;
use App\Repository\CategoryRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=CategoryRepository::class)
*/
class Category
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\OneToMany(targetEntity=Product::class, mappedBy="category")
*/
private $products;
public function __construct()
{
$this->products = new ArrayCollection();
}
// ...
// Rest of getters & setters
// ...
/**
* @return Collection|Product[]
*/
public function getProducts(): Collection
{
return $this->products;
}
public function addProduct(Product $product): self
{
if (!$this->products->contains($product)) {
$this->products[] = $product;
$product->setCategory($this);
}
return $this;
}
public function removeProduct(Product $product): self
{
if ($this->products->removeElement($product)) {
// set the owning side to null (unless already changed)
if ($product->getCategory() === $this) {
$product->setCategory(null);
}
}
return $this;
}
public function __toString()
{
return $this->getName();
}
}
这是我的控制器:
class ProductApiController extends AbstractController
{
/**
* @Route("/products", name = "api_product_list")
*/
public function getAll(SerializerInterface $serializer, ProductRepository $repo): Response
{
$products = $repo->findAll();
$jsonObject = $serializer->serialize($products, 'json', [
'circular_reference_handler' => function () {
return null;
}]
);
return new Response($jsonObject, 200, ['Content-Type' => 'application/json']);
}
}
这是我当前的输出:
{
"id": 1,
"name": "Gaming pc",
"description": "A nice computer",
"price": 9800,
"available": true,
"category": {
"id": 1,
"name": "Computers",
"products": [
null
],
"__initializer__": null,
"__cloner__": null,
"__isInitialized__": true
}
}
这是我想要得到的输出:
This is the output I want to get:
{
"id": 1,
"name": "Gaming pc",
"description": "A nice computer",
"price": 9800,
"available": true,
"category": "Computers" // Basically this is why I need a custom serializer
}
这是文档 但我不知道该怎么办.
Here is the documentation but I couldn't figure out what to do in my case.
推荐答案
src/Serializer/ProductNormalizer.php
下:(路径需要准确,否则你将不得不 手动注册)
Under src/Serializer/ProductNormalizer.php
: (The path needs to be exact, else you would have to register it manually)
<?php
namespace App\Serializer;
use App\Entity\Product;
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
class ProductNormalizer implements ContextAwareNormalizerInterface
{
private $normalizer;
public function __construct(ObjectNormalizer $normalizer)
{
$this->normalizer = $normalizer;
}
public function normalize($product, string $format = null, array $context = [])
{
$data = $this->normalizer->normalize($product, $format, $context);
$data = [
'id' => $product->getId(),
'name' => $product->getName(),
'description' => $product->getDescription(),
'price' => $product->getPrice(),
'available' => $product->getAvailable(),
'category' => $product->getCategory()->getName(), //Customize to your needs
];
return $data;
}
public function supportsNormalization($data, string $format = null, array $context = [])
{
return $data instanceof product;
}
}
这篇关于如何在 Symfony 5 中创建用于序列化 json 的自定义 Normilizer?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!