-
-
Notifications
You must be signed in to change notification settings - Fork 585
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serialize null values as empty string #566
Comments
Just solved my problem using a custom visitor: <?php
namespace Project\Namespace\Serializer;
use JMS\Serializer\Context;
use JMS\Serializer\JsonSerializationVisitor;
class BlankSerializationVisitor extends JsonSerializationVisitor
{
/**
* {@inheritdoc}
*/
public function visitNull($data, array $type, Context $context)
{
return '';
}
} And then, set it to your serializer using the |
Hi, we wanted to achieve the same, but just for string types. So we override visitString method, but it's not working. Bye |
Use a "custom/virtual" type for the string and implement a handler for it.
Disadvantages:
|
Oh, thank you a lot. I've missed this somehow in docs. Bye |
So, I did everything you said, but custom handler is called only if value is not null. If string is null, we can't change it even with custom type and custom handler. |
did you enable |
sure. I've set it in config.yml like this:
and this too:
|
It seems the way @Seb33300 mentions is now not valid, as
<?php
declare(strict_types=1);
namespace App\Serializer;
use JMS\Serializer\Exception\NotAcceptableException;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Visitor\SerializationVisitorInterface;
use JMS\Serializer\AbstractVisitor;
final class BlankSerializationVisitor extends AbstractVisitor implements SerializationVisitorInterface
{
/**
* @var int
*/
private $options;
/**
* @var array
*/
private $dataStack;
/**
* @var \ArrayObject
*/
private $data;
public function __construct(
int $options = JSON_PRESERVE_ZERO_FRACTION
) {
$this->dataStack = [];
$this->options = $options;
}
/**
* {@inheritdoc}
*/
public function visitNull($data, array $type)
{
return '';
}
/**
* {@inheritdoc}
*/
public function visitString(string $data, array $type)
{
return $data;
}
/**
* {@inheritdoc}
*/
public function visitBoolean(bool $data, array $type)
{
return $data;
}
/**
* {@inheritdoc}
*/
public function visitInteger(int $data, array $type)
{
return $data;
}
/**
* {@inheritdoc}
*/
public function visitDouble(float $data, array $type)
{
return $data;
}
/**
* @param array $data
* @param array $type
*
* @return array|\ArrayObject
*/
public function visitArray(array $data, array $type)
{
\array_push($this->dataStack, $data);
$rs = isset($type['params'][1]) ? new \ArrayObject() : [];
$isList = isset($type['params'][0]) && !isset($type['params'][1]);
$elType = $this->getElementType($type);
foreach ($data as $k => $v) {
try {
$v = $this->navigator->accept($v, $elType);
} catch (NotAcceptableException $e) {
continue;
}
if ($isList) {
$rs[] = $v;
} else {
$rs[$k] = $v;
}
}
\array_pop($this->dataStack);
return $rs;
}
public function startVisitingObject(ClassMetadata $metadata, object $data, array $type): void
{
\array_push($this->dataStack, $this->data);
$this->data = true === $metadata->isMap ? new \ArrayObject() : [];
}
/**
* @return array|\ArrayObject
*/
public function endVisitingObject(ClassMetadata $metadata, object $data, array $type)
{
$rs = $this->data;
$this->data = \array_pop($this->dataStack);
if (true !== $metadata->isList && empty($rs)) {
return new \ArrayObject();
}
return $rs;
}
/**
* {@inheritdoc}
*/
public function visitProperty(PropertyMetadata $metadata, $v): void
{
try {
$v = $this->navigator->accept($v, $metadata->type);
} catch (NotAcceptableException $e) {
return;
}
if (true === $metadata->skipWhenEmpty && ($v instanceof \ArrayObject || \is_array($v)) && 0 === count($v)) {
return;
}
if ($metadata->inline) {
if (\is_array($v) || ($v instanceof \ArrayObject)) {
// concatenate the two array-like structures
// is there anything faster?
foreach ($v as $key => $value) {
$this->data[$key] = $value;
}
}
} else {
$this->data[$metadata->serializedName] = $v;
}
}
/**
* Checks if some data key exists.
*/
public function hasData(string $key): bool
{
return isset($this->data[$key]);
}
/**
* @deprecated Use `::visitProperty(new StaticPropertyMetadata('', 'name', 'value'), 'value')` instead
*
* Allows you to replace existing data on the current object element.
*
* @param mixed $value This value must either be a regular scalar, or an array.
* It must not contain any objects anymore.
*/
public function setData(string $key, $value): void
{
$this->data[$key] = $value;
}
/**
* {@inheritdoc}
*/
public function getResult($data)
{
$result = @json_encode($data, $this->options);
switch (json_last_error()) {
case JSON_ERROR_NONE:
return $result;
case JSON_ERROR_UTF8:
throw new RuntimeException('Your data could not be encoded because it contains invalid UTF8 characters.');
default:
throw new RuntimeException(sprintf('An error occurred while encoding your data (error code %d).', json_last_error()));
}
}
}
<?php
namespace App\Serializer;
use JMS\Serializer\Visitor\SerializationVisitorInterface;
use JMS\Serializer\Visitor\Factory\SerializationVisitorFactory;
/**
* @author Asmir Mustafic <[email protected]>
*/
final class BlankSerializationVisitorFactory implements SerializationVisitorFactory
{
/**
* @var int
*/
private $options = JSON_PRESERVE_ZERO_FRACTION;
public function getVisitor(): SerializationVisitorInterface
{
return new BlankSerializationVisitor($this->options);
}
public function setOptions(int $options): self
{
$this->options = $options;
return $this;
}
}
$serializer = SerializerBuilder::create()->setSerializationVisitor('json', new BlankSerializationVisitorFactory())->build(); I don't know if there is an easier way, but it worked. |
Hi,
I would like to force the serialization of null values as empty strings
''
instead ofnull
.I set the option
setSerializeNull(true)
to force serialization of null values, but how to transform them into empty string?Maybe using the post serialize event?
But I do not understand how to use the
ObjectEvent
object. No sample is given.Thanks
The text was updated successfully, but these errors were encountered: