semicannonical-json
semicannonical json is a subset of json that avoids the float problems but considers key order in objects {} to be significant.
examples of non-cannonical floats
As @aljoscha has pointed out recently, there are a number of valid JSON expressions that are non-cannonical - that is they parse to something, but do not stringify back to the same thing. in particular, around the handling of floats.
JSON.parse('2.00000000') => 2
JSON.parse('123e456') => Infinity
but, JSON.stringify(Infinity) => "null"
so that isn't cannonical.
indeed, just the representation of the exponent is liberal in what it accepts but conservative in what it gives
JSON.parse('1e123') => 1e+123
JSON.parse('1E123') => 1e+123
obviously wether the e is upper or lower case or the + is included or not is gonna change the signature.
I've tested these cases in both V8 and firefox, and they both have the same behaviour.
handling of these cases in reference node.js implementation
I'm happy to say that these cases are implicitly forbidden in the reference implemention. if you created a message with a capital E in the exponent, it's signature would be considered invalid. sbot receives messages on the wire, parses them, then when it checks the signature: restringifies them. This means any thing which is not preserved by parsing and stringifying is excluded.
so, only the following is semi-cannonical json
json === JSON.stringify(JSON.parse(json))
that is a subset of valid json, which we fortunately already use.