JSON backward Compatibility: Flag to enable CF8 behavior

JSON serialization was
introduced in CF8 for the first time. It was used heavily to serialize CFC and
other CF data objects. In “CumulativeHotfix1 for ColdFusion 9.0.1”, some of its
outstanding issues were fixed. 
Few of issues addressed in hotfix were that of string to number
conversion, and number getting converted to double.

The change in behavior
of JSON serialization, which fixed some of the basic problems of CF developer
at one hand, also had a side effect of breaking old application built on CF8.
Migration from CF8 to later version might require making few changes in the developer’s
code.

To achieve backward
compatibility and to address a scenario where old behavior of JSON
serialization has to be retained, a JVM flag had been introduced at the same
time. If enabled, it would bypass the latest changes for JSON serialization and
fall back to CF8 behavior.

Here I am describing the JVM flag and the way to
enable it. This will bring back the old behavior where a string with leading zero like ‘000’ will be output as 0.0 rather than 000, an invalid number in javascript. Similarly all the number will be retained in double/float format. A number like 1.23E4 will be converted to 12340 and so on. So you can make use of this flag if you have got stuck upgrading to latest CF server.

To achieve the CF8 behavior, one can add a
JVM system property 
json.numberasdouble=true to jvm.config.
It is applicable to  CF “CumulativeHotfix1 for ColdFusion 9.0.1” and
later .

jvm.config file is located at  $CF_HOME/cfusion/bin/jvm.config.
Open the file and you will find “-Djava.awt.headless=true” as one of the entry
in java.args parameters.

Please add the suggested
flag just after former headless entry as  –Djson.numberasdouble=true.

 

 

18 thoughts on “JSON backward Compatibility: Flag to enable CF8 behavior

  1. Of course, you will be updating all (and future) of the CHF technote pages to point this out, right ?

    I also would like to understand how if you knew back in CHF1 that you’d changed behaviour, and so added a flag to revert it, this somehow got left out of the original and subsequent tech notes.

  2. Nice.
    I need a flag that prevents the strings “yes” and “no” being converted into json booleans and leaves as strings. I have an employee with the last name of “No”, and the conversion to boolean in json is always breaking something that I have to add special fixes for.

  3. Yes, we will be updating the CHF technote with this information. We never realized that people would face any serious issue and added the flag just for an extreme case. But later while interacting with the customer, we realized its seriousness and hence this blog is written.

  4. @Jim, as CF is a type less language, it would not be able to distinguish between ‘no’ as a string and a boolean. But I am totally agree with your concern and may provide some solution in near future.

  5. @Awdhesh I’d have no problem with a flag that removed yes/no completely from boolean interpretation. I always use true/false or zero false/non zero true integer boolean comparisons.

  6. Just wow. This was a huge effort for us. This change broke much of our UI, and resulted in us NOT applying the hotfix, as well as holding back on the upgrade to CF 10. We’ve invested hundreds of hours going through our code to completely remove the native JSON serialization.

    Stunned that this information was never shared, and that it took this long for you to realize there was an issue. Just stunned. This is an example of why I have been losing trust in the functionality provided by CF, and have been strongly considering moving away from the platform.

  7. Good to know, but you guys are way too late to be sharing this.

    Much like @Ryan Mcilmoyl, we have invested a ridiculous amount of effort trying to completely remove ColdFusion’s native serializeJSON which we rely on heavily. This effort has resulted in an inability for us meet deliverables, and has cost us many many hours in development time because we bought into CFs JSON adoption.

    Given our heavy use of CFCs and an OOP based approach to our software, we’ve had a number of frustrating GC issues using jrun when trying to do long running tasks like import/export of data, etc. CF10 using tomcat and even cf9 using java 7 both solve these issues for us, but we’ve been unable to update due to the change in serializeJSON behavior. I just can’t believe I’m finding out about this now….

  8. @Jim Partin

    regarding “yes” and “no”, one solution we’ve developed in house here is to make custom getters on any boolean property.

    public boolean function getWhatever() output=”false”{
    if(variables.whatever){
    return true;
    }
    else{
    return false;
    }
    }

  9. Preface everything I’m about to say with, I think SerializeJSON is a really well-done function, something that could easily have been a lot worse.

    I second Jim’s problem with “No” being converted to false. In CF’s ducktyping they may be the same, but JSON is an interchange format – it’s far more likely to be read by a language other than CF, most (all?) of which do not equate no and false.

    I’m currently dealing with an API that requires even numbers to be quoted, so a json.numberasstring flag would be nice too, but in reality, having to use these flags server-wide isn’t the answer. The answer should be a SerializeJSON function that takes these flags as arguments, so that each individual use-case can be addressed in their respective locations, not server-wide.

    JSON is becoming the de facto standard for data interchange. CF’s implementation should be as flexible as possible.

  10. I agree with Nick, idealy SerializeJSON should look like this:

    serializeJSON(var[, serializeQueryByColumns, options])

    options would be either an array or list of flags.

    Thus:

    myJSON = serializeJSON(myVar, options=”NumericsAsString,YesNoAsString”);

  11. @Ryan and @Adam, its unfortunate that you people have to spend extra hours to modified the code. As I remember this information was shared on few people on their personal blogs. But I am totally agreed that it would have been better if we would have shared it on CF blog. But frankly speaking We never realized that people would face any serious issue and added the flag just for an extreme case. But later while interacting with the customer, we realized its seriousness and shared the information.

  12. I agree with Nick and Jim,

    Also missing is an option to prevent serializeJSON() from prepending the Secure JSON Prefix.

    Please see http://www.petefreitag.com/item/720.cfm (As noted in Pete’s entry, he filed #80423 back 2009 – but since that was in the old tracker it’s no longer visible. Can that ticket please be made visible for voting?)

    I’d like to propose the serializeQueryByColumns not be required when using the options parameter. Example:

    SerializeJSON(var[, serializeQueryByColumns][, options])

    Additionally, I’d like to propose that the options parameter be a struct. Example:

    myJSON = serializeJSON(myVar, {addSecureJSONPrefix=false, yesNoAsString=true, etc..});

    I so agree that a list or array would be less typing w/ the list of options we’re -currently- discussing. However, I just feel a struct might offer us some flexibility in the future (ex: someFutureOption=this|that|somethingelse – meaning, at some point in the future we may want to add an option that could take one of a list of values as its value).

    Just a thought, but anyhow I definitely agree with the idea!

    Thanks,
    -Aaron

  13. oops, the “I so agree” should just be “I agree” ..tired eyes, it’s about time to call it a night!

    @Awdhesh, if you add a comment to the ticket, I likely will not see it. This is b/c the Bug Tracker *still* does not send emails to us when comments are added. Like others here, I’ve filed hundreds of tickets and it remains unfeasible for me to keep clicking on every single ticket to see if there are new comments. I truly hope the Bug Tracker team fixes that sometime soon.

    Thanks,
    -Aaron

  14. Verified that -Djson.numberasdouble=true restores CF8 behavior. Good.

    However, I still need shipment tracking number strings (ex: varchar “9876543210987654321098”) to not be serialized to floating point 9.876543210987654e+21 by CFAJAX grids.

    So in addition to a json.numberasstring JVM arg and a serializeJSON(myVar, myJSONOptions) struct, I’d also like to propose a attribute. I’d also like to propose a THIS.jsonOptions=myJSONOptions per-App setting, for setting the jsonOptions defaults app-wide.

    Whereas, myJSONOptions = {addSecureJSONPrefix=false, yesNoAsString=true, numberAsString=true};//example

    Thanks!,
    -Aaron

  15. @Aaron

    We actually ended up implementing JSONUtil.cfc and replacing the native serialization. You can then cast your values to appropriate Java objects (ie. java.lang.String) and have you types preserved on serialization. It’s a bit more work, but was the best way we could fine to achieve proper control over JSON types coming out of CF

Leave a Reply

Your email address will not be published. Required fields are marked *