benlime
Hey guys,
I have a short and simple question, which I am currently unable to figure out using the documentation of the Jason library.
I have a struct which contains some keys with values of the Decimal struct. I would like to have the Decimal struct (I am using the Decimal Library for it) always converted to float when encoding to JSON. So far I only know that I would have to implement the Json.Encoder protocol and have the encode method to call Decimal.to_float(value). But I am not sure how to do that? How do I implement the protocol?
I have tried to just make a file like this:
defimpl Jason.Encoder, for: Decimal do
def encode(struct, opts) do
Jason.Encode.map(Decimal.to_float(struct), opts)
end
end
However, this code never runs. Can anybod help? ![]()
Thanks guys.
Trending in Questions
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
I’m trying to set up Emacs with elixir-ls via lsp-mode and credo via Flycheck. This should mostly be preconfigured as Flycheck picks up c...
New
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #blog-post
- #ai
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
NobbZ
Please do not use floats. You will use all the precision you initially got by using decimal. Please do either use a String or dump into a JSON object.
Aside of that, you should use
Jason.Encode.float/1. From what I can see in the snippet you posted, the code should crash rather than not being run. Can you therefore reproduce the problem in a fresh project and put it on github?benlime
Thanks for your reply. Can you describe why using a floating point number in JSON is a bad idea? I am using
Decimalinternally to handle money values and want to return those to the frontend just for displaying in the view. Having the number as a string representation feels wrong to me. However, the default encoding encodes the value to a string. I am not sure where this logic comes from.edit: Okay I found a pretty good explanation of why I should not use floating points on StackOverflow. I get it - but just for my personal knowledge, the question still remains - even I would not use it anymore.
I don’t think a demo project is needed. I just can’t figure out how to make the code run. I only created a file
decimal_encoder.exwith the protocol implementation. But I need to use or register the implementation anywhere so that Jason knows it should use my decoder, don’t I? And this is where I am stuck.NobbZ
Floating point numbers might have their right to exist in JSON, but definitively not when your datasource is a
Decimal, asDecimalallows for very exact values, which float doesn’t.This is good.
But to be honest, in JSON the only way to represent numbers in a safe way, as JSON does not differentiate between integers and floats, but knows only about numbers. So numbers that look integral might get coerced to float without you beeing able to control.
From
jason:https://github.com/michalmuskala/jason/blob/master/lib/encoder.ex#L204-L210
So you can not change it.
And here we already have a problem. What is encoded as 1 Euro and 5 cent might get rendered as
1.05in the JSON, but as this probably not an exact value in Float this might get loaded as1.04999999(or similar) and displayed as such. Or even worse, the client truncates or rounds, or does other things out of your control.Your user has the right to get the same (or at least equivalent) information that you are working with, especially when its the users money!
benlime
Thank you so much for your explanation. This totally makes sense and I’ll stick with strings for representing money values.
I was looking at the Jason Source as I was expecting something lime this, but I must have missed it. Thanks for sharing this.
NobbZ
I knew where to look
I already assumed Jason where implementing for Decimal when I’ve seen that decimal is an optional dependency of it.
Also
defimpls are usually in the same file as the struct or the protocol, and as Jason does only define the protocol it was clear where to look, as we can safely assume that @michalmuskala organizes his code idiomatically.OvermindDL1
Ack!!!
Among others!
Never ever ever ever ever use floats in relation to money, ever ever ever!
/me hopes they were clear enough ^.^;
benlime
I think you missed one „ever“. (I got it, I got it.
)
zenw0lf
Hmm, I thought that the real problem with floats was trying to operate with them, not displaying them per se.
I know the famous:
0.1 + 0.2 # == 0.30000000000000004, but if you are operating on Decimals in Elixir and do something like:And then convert the result to a float, it’ll be present just right, as
0.3.What I’m trying to get at, in the end I always have to use
parseInt, parseFloat or Numberon the frontend to convert those decimal strings into numbers, because you usually need those values for validations, limits, steps, etc.Honest question:
Is there really a problem when going from a string representation to a float?
Is there an example of a decimal string representation that when converted to a float loses precision? Something like having
"1.05"=> converts to float =>1.049999?NobbZ
There are enough, just take
0.3, you can not represent that value as float32, the same is probably true for float64, but you can at least have a closer approximation.Play around with the float converter, it shows you what is possible and what is not.
Also, just as an exercise. Try to find
nandm:0.3 = m / (2 ** n)Even though that is not the real representation, it will give you an estimate what the problem is.
benwilson512
Sure, here’s a concrete example:
Suppose you have a service where people want to send you numbers, and you’re going to do some kind of processing with those numbers, and then send back a result. Suppose it’s super simple, like a math test for kids where they’re asked to round a number.
The task is: Round “2.675” to the nearest hundredths place.
You take that value, and parse it to a float:
Yay! that looks right!
Oh no…
This happens because it isn’t actually 2.675, it’s
2.67499999999999982236431605997495353221893310546875and Elixir is nice and displays something more friendly.Yes, if you care about precision at all. To be clear, plenty of times you don’t care about precision. Maybe you’re doing geolocation stuff where precision is carried as a separate term anyway, maybe you’re doing something in a GPU with floating point math. But if people want you to treat the number as it is written, you can’t convert it to a float, at all.