I've adapted your simple example:

Class test.TestJSONExport Extends (%RegisteredObject, %ZJSON.Adaptor)
{ 
Property int As %Integer; 
Property bool As %Boolean; 
Property str As %String(MAXLEN = ""); 

ClassMethod test()
{
    set obj = ..%New()
    set obj.bool=1
    set obj.int=12
    set obj.str="TEST"
    set sc = obj.%JSONExport()
} 
}

With this I get the following terminal-output:

do ##class(test.TestJSONExport).test()
{"int":"12","bool":"true","str":"TEST"}

Is it because I'm using the backported %ZJSON from Robert in Caché?

https://community.intersystems.com/post/backport-json-cach%C3%A9
 

Thanks!

Thomas