Skip to content

Commit

Permalink
Merge pull request #1456 from schmittjoh/float-decimals
Browse files Browse the repository at this point in the history
Float with fixed/zer-padded decimals
  • Loading branch information
goetas committed Jan 6, 2023
2 parents ebe4ee3 + 9eceb7e commit 0fa5e4f
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 34 deletions.
8 changes: 8 additions & 0 deletions doc/reference/annotations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,14 @@ Available Types:
| | Rounding Mode. |
| | (HALF_UP, HALF_DOWN, HALF_EVEN HALF_ODD) |
+------------------------------------------------------------+--------------------------------------------------+
| double<2, 'HALF_DOWN', 2> or float<2, 'HALF_DOWN', 2> | Primitive double with precision, |
| double<2, 'HALF_DOWN', 3> or float<2, 'HALF_DOWN', 3> | Rounding Mode and decimals padding up to |
| | N digits. As example, the float ``1.23456`` when |
| | specified as ``double<2, 'HALF_DOWN', 5>`` will |
| | be serialized as ``1.23000``. |
| | NOTE: this is available only for the XML |
| | serializer. |
+------------------------------------------------------------+--------------------------------------------------+
| string | Primitive string |
+------------------------------------------------------------+--------------------------------------------------+
| array | An array with arbitrary keys, and values. |
Expand Down
6 changes: 3 additions & 3 deletions src/JsonSerializationVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ public function visitInteger(int $data, array $type)
*/
public function visitDouble(float $data, array $type)
{
$percision = $type['params'][0] ?? null;
if (!is_int($percision)) {
$precision = $type['params'][0] ?? null;
if (!is_int($precision)) {
return $data;
}

$roundMode = $type['params'][1] ?? null;
$roundMode = $this->mapRoundMode($roundMode);

return round($data, $percision, $roundMode);
return round($data, $precision, $roundMode);
}

/**
Expand Down
21 changes: 17 additions & 4 deletions src/XmlSerializationVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,27 @@ public function visitInteger(int $data, array $type)
*/
public function visitDouble(float $data, array $type)
{
$percision = $type['params'][0] ?? null;
if (is_int($percision)) {
$dataResult = $data;
$precision = $type['params'][0] ?? null;
if (is_int($precision)) {
$roundMode = $type['params'][1] ?? null;
$roundMode = $this->mapRoundMode($roundMode);
$data = round($data, $percision, $roundMode);
$dataResult = round($dataResult, $precision, $roundMode);
}

return $this->document->createTextNode(var_export((float) $data, true));
$decimalsNumbers = $type['params'][2] ?? null;
if (null === $decimalsNumbers) {
$parts = explode('.', (string) $dataResult);
if (count($parts) < 2 || !$parts[1]) {
$decimalsNumbers = 1;
}
}

if (null !== $decimalsNumbers) {
$dataResult = number_format($dataResult, $decimalsNumbers, '.', '');
}

return $this->document->createTextNode((string) $dataResult);
}

/**
Expand Down
53 changes: 52 additions & 1 deletion tests/Fixtures/ObjectWithFloatProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ class ObjectWithFloatProperty
#[Type(name: 'float')]
private $floatingPointUnchanged;

/**
* @Type("float<0>")
* @var float
*/
#[Type(name: 'float<0>')]
private $floatingPointPrecisionZero;

/**
* @Type("float<2,'HALF_DOWN'>")
* @var float
Expand Down Expand Up @@ -43,18 +50,47 @@ class ObjectWithFloatProperty
#[Type(name: 'double<2, "HALF_UP">')]
private $floatingPointHalfUp;

/**
* @Type("double<2,null,2>")
* @var float
*/
#[Type(name: 'double<2, null, 2>')]
private $floatingPointFixedDecimals;

/**
* @Type("double<2,null,1>")
* @var float
*/
#[Type(name: 'double<2, null, 1>')]
private $floatingPointFixedDecimalsLess;

/**
* @Type("double<2,null,3>")
* @var float
*/
#[Type(name: 'double<2, null, 3>')]
private $floatingPointFixedDecimalsMore;

public function __construct(
float $floatingPointUnchanged,
float $floatingPointPrecisionZero,
float $floatingPointHalfDown,
float $floatingPointHalfEven,
float $floatingPointHalfOdd,
float $floatingPointHalfUp
float $floatingPointHalfUp,
float $floatingPointFixedDecimals,
float $floatingPointFixedDecimalsLess,
float $floatingPointFixedDecimalsMore
) {
$this->floatingPointUnchanged = $floatingPointUnchanged;
$this->floatingPointPrecisionZero = $floatingPointPrecisionZero;
$this->floatingPointHalfDown = $floatingPointHalfDown;
$this->floatingPointHalfEven = $floatingPointHalfEven;
$this->floatingPointHalfOdd = $floatingPointHalfOdd;
$this->floatingPointHalfUp = $floatingPointHalfUp;
$this->floatingPointFixedDecimals = $floatingPointFixedDecimals;
$this->floatingPointFixedDecimalsLess = $floatingPointFixedDecimalsLess;
$this->floatingPointFixedDecimalsMore = $floatingPointFixedDecimalsMore;
}

public function getFloatingPointUnchanged(): float
Expand All @@ -81,4 +117,19 @@ public function getFloatingPointHalfUp(): float
{
return $this->floatingPointHalfUp;
}

public function getFloatingPointFixedDecimals(): float
{
return $this->floatingPointFixedDecimals;
}

public function getFloatingPointFixedDecimalsLess(): float
{
return $this->floatingPointFixedDecimalsLess;
}

public function getFloatingPointFixedDecimalsMore(): float
{
return $this->floatingPointFixedDecimalsMore;
}
}
25 changes: 0 additions & 25 deletions tests/Serializer/JsonSerializationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use JMS\Serializer\Tests\Fixtures\AuthorList;
use JMS\Serializer\Tests\Fixtures\FirstClassMapCollection;
use JMS\Serializer\Tests\Fixtures\ObjectWithEmptyArrayAndHash;
use JMS\Serializer\Tests\Fixtures\ObjectWithFloatProperty;
use JMS\Serializer\Tests\Fixtures\ObjectWithInlineArray;
use JMS\Serializer\Tests\Fixtures\Tag;
use JMS\Serializer\Visitor\Factory\JsonSerializationVisitorFactory;
Expand Down Expand Up @@ -446,30 +445,6 @@ public function testTypeHintedArrayAndStdClassSerialization(array $array, $expec
self::assertEquals($expected, $this->serialize($array, $context));
}

public function testSerialisationWithPercisionForFloat(): void
{
$objectWithFloat = new ObjectWithFloatProperty(
1.555555555,
1.555,
1.15,
1.15,
1.555
);

$result = $this->serialize($objectWithFloat, SerializationContext::create());

static::assertEquals(
'{'
. '"floating_point_unchanged":1.555555555,'
. '"floating_point_half_down":1.55,'
. '"floating_point_half_even":1.2,'
. '"floating_point_half_odd":1.1,'
. '"floating_point_half_up":1.56'
. '}',
$result
);
}

protected function getFormat()
{
return 'json';
Expand Down
10 changes: 9 additions & 1 deletion tests/Serializer/XmlSerializationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -570,13 +570,17 @@ public function testDoubleEncoding()
setlocale(LC_ALL, $locale);
}

public function testSerialisationWithPercisionForFloat(): void
public function testSerialisationWithPrecisionForFloat(): void
{
$objectWithFloat = new ObjectWithFloatProperty(
1.555555555,
1.555555555,
1.555,
1.15,
1.15,
1.555,
1.5,
1.555,
1.555
);

Expand All @@ -586,10 +590,14 @@ public function testSerialisationWithPercisionForFloat(): void
'<?xml version="1.0" encoding="UTF-8"?>
<result>
<floating_point_unchanged>1.555555555</floating_point_unchanged>
<floating_point_precision_zero>2.0</floating_point_precision_zero>
<floating_point_half_down>1.55</floating_point_half_down>
<floating_point_half_even>1.2</floating_point_half_even>
<floating_point_half_odd>1.1</floating_point_half_odd>
<floating_point_half_up>1.56</floating_point_half_up>
<floating_point_fixed_decimals>1.50</floating_point_fixed_decimals>
<floating_point_fixed_decimals_less>1.6</floating_point_fixed_decimals_less>
<floating_point_fixed_decimals_more>1.560</floating_point_fixed_decimals_more>
</result>',
$result
);
Expand Down

0 comments on commit 0fa5e4f

Please sign in to comment.