Does anybody know how to generate PascalCase json ...
# cfml-general
s
Does anybody know how to generate PascalCase json from serializeJSON()? Or camelCase for that matter? Anyone, how to change the casing of the resulting json 🙂.
w
are you saying your base struct or array in cf does NOT have the correct key case?
prior to serialization
because if you use square bracket notation rather than dot notation the case will be preserved when serializing to json (except in very old cf versions)
d
I think you have to put your keys in quotes to maintain the casing. Something like this:
Copy code
myStruct = {
    "MyKeyName": "this key value",
    "MyOtherKeyName": "another key value"
};
serializeJSON(myStruct);
w
or quoted keys yes
this udf will force upper or lower case keys as written but it would be no big deal to modify it to support pascal or camel case as well if you need to correct key case before you serialize:
Copy code
/**
     * Takes a struct or array (which contains nested structs) and forces struct key names to upper or lowercase as specified; ensures predictable results when using serializeJSON et al
     * 
     * @object any 	               	only structs and arrays (which contain structs) are operated upon
     * @forcecase string            ?: upper | lower - the case to force the struct's keys to
     * 
     * @return any               	the object with struct key case modifications in place
     */
    public any function forceStructKeyCase( 
        required any object, 
        string forcecase="upper"
    ) output=false {
	
		var x = {};
		var y = "";
		var i = "";
		var a = ""; 
		var z = [];

		if(isArray(arguments.object)) {

			if(!arraylen(arguments.object)) {
				return arguments.object; 
			}
			else {
				for(a = 1; a lte arraylen(arguments.object); a++) {
					z[a] = forceStructKeyCase(object=arguments.object[a],forcecase=arguments.forcecase);
				}
			}
			return z; 

		}
		else if(isStruct(arguments.object)) {

			if(!structisempty(arguments.object)) {
				for(i in arguments.object) {
					y = ucase(i);
					if(arguments.forcecase eq "lower") {
						y = lcase(i);
					}
					x[y] = forceStructKeyCase(object=arguments.object[i],forcecase=arguments.forcecase);
				}
			}
			return x;

		}
		else {			
			return arguments.object; 
		}

	}
s
@websolete, our use case is the following: We have a component Foo, as such:
Copy code
property name="propOne"; 
property name="propTwo";
...
And this should be sent to an external API as json, but the external API expects the keys in PascalCase, but we define them as camelCase (as per our design standards / requirements). I was looking for a way to make these two ends meet in the middle (custom serializer / etc...)
w
i would still modify the udf above to allow specifying pascal, get your properties as a struct (variables scope) and update the key case prior to serialization. cf won't care of course.
from what it looks like, all you need to do is capitalize the first char of what you already have and you're done
alternatively, you could just adopt pascal for the property names and not do any mods, since cf again won't care
z
CF does care, it's a lovely person
😎 1
s
@websolete b/c i am a stubborn person, i just wrote a custom serializer
I do not care about the performance hit my code probably causes, it does what it needs to to, without me having to change ALL my components
Problem 1 solved. On to problem 2: is it possible to serialize nested json into a component?
q
myVar = {};
myVar["myStuct"] = {};
myVar.myStruct.property = "value";
myVar.myStruct.property2 = "value;
myJSON = serializeJSON(myVar);
That will capture the right case of the property as well as the nested json components.
m
My experience has been that serializeJSON handles arbitrarily nested structs/arrays. The only issue I've run into is that it gets fancy with date values and thinks it knows how to format them when it does, in fact, not know how to format them.
they come out as things like
November, 5  2023
and I'm all who even puts a comma after the month instead of the day? Not even a thing CF, c'mon.
s
It got it working for my particular use case, albeit kinda hackish
👍 1
Anyhow, thanks to everyone to put in thinking effort!
q
Dates are weird. In my final output, I usually end up storing them as a string and manually serializing it on the way out. That way ACF/Lucee can't make bad decisions.
m
I ended up pre-formatting before handing off to serializeJSON and it avoided the trampling of the values. I think as long as the built-in serializer doesn't recognize it as a date, it'll think it's just a text string and leave it alone. Which is funny, since I formatted it as something that JS recognizes when I pass it to
new Date(myString)
q
CF being classless and having to guess at variable types all the time is it's biggest weakness.. And we don't have a ton of ways to guide it to making better decisions.
👍 1
k
I use the following to convert nested structs (and structs in arrays) to lowercase. can be modified to suit your need.
Copy code
// Below function sorts nested structs & convert keys to lowercase
// v = incoming value(struct), s = flag to sort the struct
function structSortLowerCase(v, s=1) {
	if (isStruct(v)){
		if (s){ v = structToSorted(v,"text","asc"); } // sort the struct
		structEach(v, function(key,value) { v["#lcase(key)#"] = value; } );	// lowecase the keys
		//make a nested/circular call to structSortLowerCase on the values
		return structMap(v, function(key,value) { return structSortLowerCase(value); } );
	}
	else if ( isArray(v) ) { return arrayMap(v, function (value) { return structSortLowerCase(value); } ); }
	else {  return v; }
}