ILCAI
ILCAI

Reputation: 1234

Symfony serializer returns string instead of float

How can the Symfony Serializer Component be configured to normalize a float property of an object (entity)?

In detail: the taxRate property of a doctrine entity is is mapped to a PHP float value. And I would like to respond from a controller with a JSON representation like:

{taxRate:0.19}

But what I get is

{taxRate:"0.19"}

The definition of the entity's property and annotations are:

class ExampleEntity {
  /**
   * @ORM\Column(type="decimal", precision=3, scale=2, nullable=true)
   * @Groups({"api"})
   */
  protected $taxRate;
}

The controller looks like this:

$serializer = $this->get('serializer');
return new JsonResponse(
  $serializer->normalize(
    $exampleEntity,
    'json',
    [
      'groups' => 'api',
    ]
  )
);

I don't like the solution of converting the string into a Float on the JavaScript side. My app would like to assert the property is NULL or a Float value.

How can this be done?

Upvotes: 4

Views: 5105

Answers (3)

Artem
Artem

Reputation: 1646

For decimal type values retrieved from the database are always converted to PHP's string type or null if no data is present.

Doctrine Documentation

If you want to use decimal, change the getter for property

public function getTaxRage(): ?float
{
    return is_string($this->taxRate) ? (float) $this->taxRate : $this->taxRate;
}

Upvotes: 0

Johnson
Johnson

Reputation: 116

I had the same issue with Symfony 4.4 serializer, and I disagree with your solution. I resolved my problem by changing type="decimal" to type="float", as some people already suggested it in the comments. A proper type hinting is a good practice. Why using a string when you can use a float?

Float type, from doctrine documentation :

https://www.doctrine-project.org/projects/doctrine-dbal/en/2.12/reference/types.html#types

Maps and converts numeric data with floating-point precision. If you only need an approximate precision for numbers with fractions, you should consider using this type. Values retrieved from the database are always converted to PHP's float/double type or null if no data is present.

Some additionnal information about this approach :

  • Symfony serializer does read your ORM annotations if you instantiate it well using a service container
  • Symfony serializer is perfectly abble to consider floats as floats
  • Doctrine needs a precision for a float, PHP doesn't, and it's totally OK. You can insert a float in your database, Doctrine will round it if necessary.

A float attribute example for the serializer :

/**
 * @var float|null
 * @ORM\Column(type="float", precision=6, scale=2, nullable=true)
 */
protected $ratio;

/**
 * @return float|null
 */
public function getRatio(): ?float
{
    return $this->ratio;
}

/**
 * @param float|null $ratio
 * @return $this
 */
public function setRatio(?float $ratio): self
{
    $this->ratio = $ratio;
    return $this;
}

Upvotes: 0

ILCAI
ILCAI

Reputation: 1234

Thanks to the comments, I think the question is not very clear/can be removed.

The serialization process is fine, it's the mapping from Doctrine which I did not get right.

It is totally OK, DECIMAL Doctrine/MySQL types are mapped to PHP strings. DECIMAL is designed to guarantee a precision for a numeric value. PHP's float type cannot guarantee the same precision.

Upvotes: 1

Related Questions