jessarcher / laravel-castable-data-transfer-object

Automatically cast JSON columns to rich PHP objects in Laravel using Spatie's data-transfer-object class
https://jessarcher.com/blog/casting-json-columns-to-value-objects/
MIT License
328 stars 23 forks source link

Prevent float to be convert #5

Closed BaraoVlask closed 3 years ago

BaraoVlask commented 3 years ago

https://github.com/jessarcher/laravel-castable-data-transfer-object/blob/1e02006ba4b92157abe3c9299b1c3eb03263324a/src/CastableDataTransferObject.php#L20

As this StackOverflow says that json_enconde treats float's and integers as numbers when a float ends with .0, it is converted to an integer and then an incorrect one is saved in the database like this example:

array:4 [
  "valorMinimoPorAposta" => 0.0
  "retornoMaximoPorAposta" => 999999999999.99
  "quantidadeMinimaDeJogosPorAposta" => 1
]

the code generate this json

{"valorMinimoPorAposta":0,"retornoMaximoPorAposta":999999999999.99,"quantidadeMinimaDeJogosPorAposta":1}

Although I managed to make a workaround I think it's a good one idea to use this JSON_PRESERVE_ZERO_FRACTION setting in the mentioned code, but I don't really know about code patterns. Thanks for listening. Translated by Google. :|

jessarcher commented 3 years ago

Olá @BaraoVlask!

Thank you for pointing this out. I am familiar with the problem, but I did not know about JSON_PRESERVE_ZERO_FRACTION so thank you for teaching me!

In my own DTO classes I am using a union type of float|int. I think I would still need this because Laravel's Request object automatically deserializes JSON requests and it does not appear to use that flag.

I can't see any problems with your idea, but I don't have time to implement and test it right now. I will try to get to it soon.

Valeu!

jessarcher commented 3 years ago

Hey @jrmajor, do you have any thoughts on this proposed change for the next major release?

jrmajor commented 3 years ago

@jessarcher Implementing Jsonable would require us to add $options = 0 parameter to toJson() method. We can pass the JSON_PRESERVE_ZERO_FRACTION flag there, but Laravel doesn't use any flags when casting arrays/collections, which makes me hesitant to enable this behavior as a default.

jrmajor commented 3 years ago

@jessarcher I will try to make it a cast parameter. Please, wait for one more PR before tagging v2 :)