customizing JSON serialization
# lucee
d
customizing JSON serialization
is there a way to hook into json serialization? Or override the default serializer or whatever, for
serializeJSON
Lucee docs provide this signature, nothing to hook into that I see beyond a minor affordance for outputed shape of a serialized query:
Copy code
SerializeJSON( var=any, queryFormat=any, useSecureJSONPrefixOrCharset=any, compact=boolean );
INB4 "use case": I need any object derived from
java.util.Date
to be serialized in a particular way.
Copy code
package lucee.runtime.converter;
public JSONConverter(boolean ignoreRemotingFetch, Charset charset) {
		this(ignoreRemotingFetch, charset, JSONDateFormat.PATTERN_CF, true, null);
}
public JSONConverter(boolean ignoreRemotingFetch, Charset charset, String pattern) 
public JSONConverter(boolean ignoreRemotingFetch, Charset charset, String pattern,
or use a particular "JSONConverter" with a particular "(date format) pattern"
s
short answer: no. long answer: yes but then you're specifying a custom serializer, meaning a) you need a custom serializer and b) performance is likely to suffer; a couple people have done it IIRC
might be a way to get mementifier to do the heavy lifting
so that it's just a string by the time you're serializing it
d
It's not well exposed, but there is a date pattern argument to the built in serializer. It is
public static final String PATTERN_CF = "MMMM, dd yyyy HH:mm:ss Z";
so providing a custom pattern string to an instance of a native lucee serializer would be of equivalent performance; now, do they make it ergonomic to do so? Maybe not.
s
yeah, that's adobe compat, some boneheaded adobe engineer decided 'February, 02 2024' was a good format
lucee emulated it
d
so it is configurable but they soft-cache it based on current locale, so you can only set it once until a magic key is GC'd
Copy code
public static String format(Date date, TimeZone tz, String pattern) {
		tz = ThreadLocalPageContext.getTimeZone(tz);
		String id = locale.hashCode() + "-" + tz.getID();
		synchronized (sync) {
			SoftReference<DateFormat> tmp = map.get(id);
			DateFormat format = tmp == null ? null : tmp.get();
			if (format == null) {
				format = new SimpleDateFormat(pattern, locale);
				format.setTimeZone(tz);
				map.put(id, new SoftReference<DateFormat>(format));
			}
			return format.format(date);
		}
	}
s
there is likely a bunch of code expecting it to work the way it does now
if we can invoke it in NewBetterWay without mangling that, works for me
d
If I'm understanding this right, you can have one pattern string for all of jsonSerialize, per timezone. Hm, yeah not gonna fly.
l
It's not ideal, but I've seen examples where a regex in conjunction with reReplaceNoCase was used after serialization to change the dates in the json string.
g
I was going to suggest post regex processing - But @Larry Lopez beat me to it! As for what you "really" want. It certainly wouldn't hurt to submit a feature request and ask forum followers to go and up-vote it - with you - to get it to the attention of the Lucee Devs. They are ALWAYS keen to innovate - where it helps "us" out. Lastly - @sknowlton mentioned that Lucee "emulated" Adobe's (seemingly) stupid, default datetime formatting... Just in case anyone wasn't aware of it - Lucee prioritizes "compatibility" with ACF - as opposed to "emulating" them. ( Editorial: As "I" was reading Sam's comment - it sounded to me like he was suggesting that Lucee "just", naively/blindly followed Adobe CF, without any real thought. And that most certainly may not have been Sam's attention, at all... But I thought I should put a "defence" of Lucee out into the Universe - for balance! I am sure we all know of features / tuning that Lucee has done for CFML that Adobe doesn't have or care about. And to play devil's advocate - against myself - I am sure we're also aware that despite my defence of the Lucee dev team - there ARE plenty of examples of "not-quite-right" solutions, in Lucee CFML, too! )
t
if performance is not a concern, you can use some custom Json Serialization functions ppl already created I took the JsonEncode() function on cflib.org by Jehiah Czebotar and added some improvement (you can format date & time to any format you want, also there is a "strict" mode so that CF/Lucee won't change string likes "1" "true" into boolean)
d
If the data you're serializing is pretty basic (i.e. a query, array, struct that's basically one level deep), you could always use
map()
to loop through and format the dates prior to serializing to convert them into a string of your desired format. If you use an single instance of
java.text.SimpleDateFormat
to format the dates, it's pretty performant. However, if the data is complex, deeply nested or you just generally need all dates formatted a specific way, then a custom serializer is probably the best choice. Take a look at this thread too: https://dev.lucee.org/t/serializejson-and-datetime/7887/4
s
@gavinbaumanis I didn't mean 'emulated' pejoratively, in stuff like that the expectation is that Lucee will do what ACF does because otherwise everyone will complain about how it's not compatible 🙂 having converted a couple big apps from CF11 to Lucee a while back, I would not have appreciated a default configuration that was substantively different than what Adobe did
👍🏼 1
l
What could also potentially help, is if Lucee added the ability to tag structs with metadata like ACF added in 2016.