How can I prevent SerializeJSON from changing Yes/No/True/False strings to boolean?
Asked Answered
B

7

15

I have a data struct being stored in JSON format, converted using the serializeJSON function. The problem I am running into is that strings that can be boolean in CF such as Yes,No,True,and False are converted into JSON as boolean values. Below is example code. Any ideas on how to prevent this?

Code:

<cfset test = {str='Yes'}>
<cfset json = serializeJSON(test)>
<cfset fromJSON = deserializeJSON(json)>

<cfoutput>
    #test.str#<br>
    #json#<br>
    #fromJSON.str#
</cfoutput>

Result:

Yes
{"STR":true}
YES
Blazer answered 8/12, 2009 at 15:33 Comment(2)
Well I just came up with a solution. Adding an extra space in the string is a way to prevent it from being converted to boolean. This works for my current need but any better solutions would be appreciated so I don't have to manipulate the string before conversion.Blazer
Got the same problem even if I make the JSON myself without using serializeJSON()Lavelle
B
6

Adding an extra space in the string to prevent it from being converted to boolean, then trim at a later stage.

Blazer answered 6/11, 2010 at 12:22 Comment(0)
C
4

I believe that your or any similar "string forcing" workaround is the only possible way to prevent such behavior in Adobe CF for now.

BTW, Railo works as expected with your example. Here is the output:

Yes
{"STR":"Yes"}
Yes 

It is also works same way for the numbers with trailing zeros.

Coast answered 8/12, 2009 at 16:4 Comment(5)
We are on CF8 at the moment. Do you know how it is converted in CF9?Blazer
@Dan Knowing the background of legacy code support by Adobe, I could bet that default behavior not changed yet. But I've checked it for you: no changes. Also manual shows that there are no new arguments can overridde it yet: help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/…Coast
In CF9,0,0,251028 it is {"STR":true}Decumbent
@Sergii. Whoops. I did not see your response.Decumbent
Where can I set this setting in CF9?Shoeblack
F
3

Here's good news for those running CF2018 and 2021. The code in the original post (from cf9 in 2009) does indeed now return was Dan Roberts was expecting:

Yes
{"STR":"Yes"}
Yes

That's without any need of specifying any non-default settings in the app, application.cfc, admin, or jvm args.

Curiously, CF2016 (even the final update, 17) does still return:

Yes
{"STR":true}
YES

But as was noted by kuhl in another answer here, you CAN get the desired behavior in CF2016 with the setmetadata function (and it still works fine in 2018 and 2021, of course). Here it is, as script:

<cfscript>
   // changing the default serialization by specifying the datatype of the "str" struct key to be  string
   metadata = {str: {type:"string"}};
   test.setMetadata(metadata);
   writeoutput(SerializeJSON(test));
</cfscript>

which produces:

{"STR":"Yes"}
Ferebee answered 9/6, 2021 at 21:18 Comment(0)
D
2

it's hacky, but if you conditionally output yes and no as "_yes_" and "_no_" (using a switch statement and then after serialising the JSON to a string, do a search and replace, it works.

raw_json=serializeJSON(object);
raw_json=ReplaceNoCase(raw_json,':"_Yes_"',':"Yes"',"ALL"); 
raw_json=ReplaceNoCase(raw_json,':"_No_"',':"No"',"ALL");

at least CF is consistantly frustrating with this, true & false get converted to yes no when you round trip the data

Disulfide answered 12/7, 2011 at 8:33 Comment(0)
T
1

Use JsonSerializer.cfc by Ben Nadel

Ty answered 25/2, 2014 at 1:44 Comment(0)
D
0

I know this answer would not have worked when the question was asked, but as this seems to be the one that people are finding when researching this issue, I thought it would be good to update with a new fix.

For those on CF2016, Adobe has implemented a new function to help fix this issue. This would be preferable to adding a space to the front of strings, though that would still need to be the work around for releases before CF2016 as described by Sergii.

For Structs in CF2016:

Use the struct function, setMetadata, to specify the metadata.

The metadata is a struct where each key is struct key and the value of each key specifies the information on how to serialize in JSON.

The value of the key can be a string or a struct.

Value as string

metadata = {firstname: "string"}};

Value as struct

metadata = {firstname: {type: "string"}};

Example:

<cfscript>
       example = structnew();
       example.firstname = "Yes";
       example.lastname = "Man";
       // changing the default serialization by specifying the type of "firstname" as string
       metadata = {firstname: {type:"string"}};
       example.setMetadata(metadata);
       writeoutput(SerializeJSON(example));
</cfscript>

For Queries in CF11+: Adobe reports that they've fixed this issue.

Dinka answered 24/8, 2017 at 16:32 Comment(5)
What about when my data is coming from a storedproc? I'm having this issue using cfstoredproc. The SP itself is returning proper strings, but as it filters through the cfstoredproc tag, it gets changed.Gascony
@ReverendDovie according to Adobe, CF11 and up has fixed this issue for queries without needing additional code as long as you convert the query straight to JSONDinka
Except that it's doing it to me. I'm on CF2016 and I used cfstoredproc to run a SP. I verified in SQL developer that the SP returns "Yes" but I dumped the data immediately after the cfstoredproc tag and it was reset to true.Gascony
@ReverendDovie I have a coworker who's seeing the same as you when returning from DB2. So it may not be a 100% fix.Dinka
Figured it out. I was wrong. the data came back fine, but was getting screwed up with an implicit call to CFserializeJSON. My boss had his own version rolled already, so we "short-circuited" the cfc to use that instead and it all works now!Gascony
T
-2

I'd try javacasting it: key = javacast("string", "yes"). That should force CF to recognize it as a string rather than as a boolean.

Thacher answered 15/12, 2009 at 1:11 Comment(2)
didn't change result in my testingBlazer
Doesn't work... however, JavaCast is useful for making sure numbers are ints and not floats.Pharaoh

© 2022 - 2024 — McMap. All rights reserved.