`args = {};` `args.amount = 230*100;` `writedump(s...
# cfml-general
d
args = {};
args.amount = 230*100;
writedump(serializeJSON(args));abort;
Gives the result: {"amount":23000.0} WTF?! Why the trailing .0? The only solution I came up with is:
args.amount = javaCast("int", 230*100);
Is there a better way? This is in ACF2023, in ACF2016 it worked as expected.
a
Just
int(args.amount)
should do the trick, and more idiomatically. But yeah a bit odd that two ints multiplied end up being a double.
d
Thanks mate. Have you played with ACF2023 much. I've spent about 10 mins so far and buggy as. "*Preserve case for Struct keys for Serialization" ignores local scope as far I can tell.*
a
The CF2023 Docker image is broke, I've reported it but no action thusfar. So... can't use it even if I want to. Which I only would or the sake of answering ppl's questions anyhow.
I'd swerve it until the first serious updater though anyhow. Same advice as ever.
d
Is there a place to file these bugs?
a
@Mark Takata (Adobe) can you find out why the CF Team thought that multiplying two Integers ought to result in a Double?
https://tracker.adobe.com/#/home, It's kinda like screaming into the abyss though
s
I just tried this on ACF 10, 11, 2016, 2018, 2021 and they all show `23000.0`:
Copy code
writeoutput(serializejson({amount: 230 * 100}));
(well, 2018 is broken on trycf.com right now -- everything produces a syntax error)
So I'm going to guess this is Adobe thinking "JS only has floating point, not integers, so we'll make JSON have floating point values"...
int(230 * 100)
produces
23000
on 11, 2016, 2021... but produces
23000.0
on 10.
On 10 you need
javacast("int", 230 * 100)
to get an integer in JSON
d
Thanks @seancorfield, thanks for testing that, true madness.
s
Well... CF is pretty loosey-goosey with numbers and it mostly treats them as strings and doubles: https://trycf.com/gist/4e882f5ca3bfed4b0d01ff604f9ee7e3/acf?theme=monokai
ACF 10: String, String, String, Double, Double, Double ACF 2021: java.lang.Integer, coldfusion.runtime.CFDouble, coldfusion.runtime.CFDouble, java.lang.Double, java.lang.Double, java.lang.Double
(that changed in 18 or 21 -- can't tell since 18 doesn't run -- ACF 2016 was the same as ACF 10/11: String, String, String)
On Lucee, those have always all been java.lang.Double (from way back on Railo 4.2 up to Lucee 6 beta)
m
Good lord people. Can someone broad stroke this for me, I was hiking in Cold Canyon.
s
@Mark Takata (Adobe) I think the TL;DR is "no action required" -- the underlying CF behavior changed in either the 2018 or 2021 release (to improve type handling) but the
serializeJSON()
behavior has been the same since at least ACF 10. I think the OP was just surprised by that long-standing behavior.
m
OK, got it. Thank you Sean. Apologies, we are dealing with a very difficult family issue here since Friday evening and my nerves are frayed a bit. Appreciate the explanation. @davequested we are DEFINITELY interested in ideas for improving language handling in CF in future versions. @Charvi is here listening intently for use cases, ideas and requests.
b
Hi @davequested, I think there is no WTF about it - the result you obtained is OK. It is even as expected. Hear me out: • ColdFusion being weakly-typed, (1.0 is 1) is true in CFML. Anyway, if you dump args you will see that the value doesn't include the decimal point. The decimal point is added during serialization. Adobe's documentation on SerializeJson provides a caveat: "At runtime, ColdFusion tries to make its best guess to determine the datatype, which may cause some unexpected behavior. For example, at the time of JSON serialization, ColdFusion attempts at converting a string to a number. If the attempt is successful, then the passed data type is treated as number irrespective of whether you wanted it to be a string or not." • One way to get what you want is to cast to integer, then apply setMetadata:
args.amount = int(230*100);
argsMetadata = {amount: {type: "string"}};
args.setmetadata(argsMetadata);
writedump(serializeJSON(args));
abort;