JSON 2.0 (and Jxon) - JSON lib for AutoHotkey
Re: JSON / JSON2 [ AHK v.1.1+ and AHK v2.0-a049 ]
Updated OP to reflect recent changes.
Re: JSON / JSON2 [ AHK v.1.1+ and AHK v2.0-a049 ]
Great-o!
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
Updated OP based on some recent internal changes. The main feature of the update is the better exception handling. See Exception Handling in OP.
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
Using this library here!
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
That's great!GeekDude wrote:Using this library here!
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
Any ideas on why this does not work?
Code: Select all
mc := new MyClass()
class MyClass{
__New(){
MsgBox % this.JSON.Dump({a: "hello"})
}
#Include JSON.ahk
}
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
I found the culprit, the recursive calls(specifically lines #194 & #196) uses JSON.Dump() instead of this.Dump(). Since it's a nested class, JSON in this case is not a global variable. I'll push the fix later today.evilC wrote:Any ideas on why this does not work?
Code: Select all
mc := new MyClass() class MyClass{ __New(){ MsgBox % this.JSON.Dump({a: "hello"}) } #Include JSON.ahk }
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
@evilC: I've pushed a new branch with the recent changes. Apparently, providing support for allowing usage as nested class(via #Include) is a little bit tricky and presents several potential issues:
- Nested class(es) such as JSON.Object and JSON.Array will not be able to reference the parent class unless the parent class passes a reference to itself through some means(e.g.: via __New or others). Neither will they be able to inherit from sibling class(es) since class Nested extends JSON.Sibling is no longer valid as JSON.Sibling is now YourClass.JSON.Sibling
- Functions(if any were to be added) will not be callable since they are now YourClass.SomeFunction()
Code: Select all
mc := new MyClass()
#Include JSON.ahk
class MyClass{
__New(){
MsgBox % this.JSON.Dump({a: "hello"})
}
class JSON extends JSON {
}
}
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
Yeah, no biggie.
I don't mind JSON polluting the global namespace anyway, as it is a command that is so universal and should be part of AHK anyway.
Thanks for looking into it though.
Am loving this lib - using it for a lot of stuff lately.
Just tried using it to dump a class instance, and it seems fine - no trace of Function names or anything in there, even with inherited classes.
How hard would it be to include an option for Dump() to strip all properties that start with an underscore?
That way,you could have classes with loads of unimportant values _underscore prefixed, and when the library dumps the class, they get stripped out - leaving you with just the properties you wish to preserve.
Yeah, I could do that myself, but if your code already iterates through the object, it would save another pass.
I don't mind JSON polluting the global namespace anyway, as it is a command that is so universal and should be part of AHK anyway.
Thanks for looking into it though.
Am loving this lib - using it for a lot of stuff lately.
Just tried using it to dump a class instance, and it seems fine - no trace of Function names or anything in there, even with inherited classes.
How hard would it be to include an option for Dump() to strip all properties that start with an underscore?
That way,you could have classes with loads of unimportant values _underscore prefixed, and when the library dumps the class, they get stripped out - leaving you with just the properties you wish to preserve.
Yeah, I could do that myself, but if your code already iterates through the object, it would save another pass.
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
Sounda a little out of scope/unnecessary for most people to me. If you want to do it yourself I'd imagine it'd be pretty simple.
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
I used this library to implement persistent and per-profile settings in my ProfileHandler library.
This massively simplified my code over using IniRead / IniWrite - I could just dump the whole settings object to file
This massively simplified my code over using IniRead / IniWrite - I could just dump the whole settings object to file
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
Do you have any plans for a reserved keyword error or warning? For example, when I try to deserialize {"_NewEnum": "Dummy"} to a normal array prototype I might expect it to error instead of giving me a borderline unloopable array. Something like that would reduce the risk of a targeted (or even accidental) attack on my scripts being able to break things.
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
I've been working on a safer array prototype that should negate any reserved keyword issues, and it seems to work. Am I missing anything obvious? Other than that it won't work for keys that don't cast to string, such as object keys (which wouldn't be used with JSON anyways).
Code: Select all
#NoEnv
SetBatchLines, -1
y := new SafeObj
y.__Set := "Setter"
y.base := "Proto"
y.__Get := "Getter"
y._NewEnum := "Enumerator"
y.__Call := "Caller"
for k, v in y
MsgBox, %k%: %v%
class SafeObj
{
static Table := {}
__New()
{
SafeObj.Table[this] := {Data: {}, Enum: ""}
}
__Set(k, v)
{
return SafeObj.Table[this].Data["|" k] := v
}
_NewEnum()
{
SafeObj.Table[this].Enum := SafeObj.Table[this].Data._NewEnum()
return this
}
Next(ByRef k, ByRef v)
{
val := SafeObj.Table[this].Enum.Next(k, v), k := SubStr(k, 2)
return val
}
__Get(k)
{
if (k != "_NewEnum")
return SafeObj.Table[this].Data["|" k]
}
}
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
@GeekDude: My apologies, I can't really put a full response at the moment. A more flexible alternative that I was thinking is to actually mimic Javascript's JSON.parse() and JSON.stringify() by providing a reviver(for parsing) and a replacer(for stringify) parameters. It will allow the caller to whitelist/blacklist(or even return a custom value) properties of their choosing rather than just blacklisting a handful of constants.
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
I'm not really familiar with how javascript's system, but my solution doesn't just blacklist a handful of constants. It adds a pipe to the beginning of every dict key so that you don't have to worry about a collision with a reserved keyword (assuming Lex doesn't go crazy and add a reserved keyword starting with pipe). It doesn't block the keys from being used, it lets you use them safely.
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
JSON.parse() wrote:If a reviver is specified, the value computed by parsing is transformed before being returned. Specifically, the computed value, and all its properties (beginning with the most nested properties and proceeding to the original value itself), are individually run through the reviver, which is called with the object containing the property being processed as this and with the property name as a string and the property value as arguments. If the reviver function returns undefined (or returns no value, e.g. if execution falls off the end of the function), the property is deleted from the object. Otherwise the property is redefined to be the return value.
Code: Select all
reviver(this, key, value) { ; the object containing the property is passed as 'this'
if (key ~= "^__((G|S)et|New|Call|Delete)$")
return get_meta_func_ref(SomeClass, key, value)
else if (key = some_reserved_key)
throw Exception(msg, args*)
return value ; return unchanged
}
Json_Load(text, Func("reviver"))
JSON.stringify() wrote:The replacer parameter can be either a function or an array. As a function, it takes two parameters, the key and the value being stringified. The object in which the key was found is provided as the replacer's this parameter. Initially it gets called with an empty key representing the object being stringified, and it then gets called for each property on the object or array being stringified. It should return the value that should be added to the JSON string, as follows:
- If you return a Number, the string corresponding to that number is used as the value for the property when added to the JSON string.
- If you return a String, that string is used as the property's value when adding it to the JSON string.
- If you return a Boolean, "true" or "false" is used as the property's value, as appropriate, when adding it to the JSON string.
- If you return any other object, the object is recursively stringified into the JSON string, calling the replacer function on each property, unless the object is a function, in which case nothing is added to the JSON string.
- If you return undefined, the property is not included in the output JSON string.
Code: Select all
replacer(this, key, value) {
if (IsObject(value) && IsFunc(value)) ; method
return your_custom_serialization(value)
return value ; do nothing
}
Json_Dump(value, Func("replacer"), indent)
Re: JSON / Jxon [ AHK v.1.1.17.00+ and AHK v2.0-a058 ]
static JSON := JSON would be more efficient.Coco wrote:class JSON extends JSON {
}
Ironically, this is not safe.GeekDude wrote:SafeObj.Table[this] := ...
- this contains a reference to SafeObj (= this.base).
- SafeObj contains a reference to the Table object.
- The Table object contains a reference to this (as a key).
- Goto 1.
This should be sufficient:
Code: Select all
#NoEnv
SetBatchLines, -1
y := new SafeObj
y.__Set := "Setter"
y.base := "Proto"
y.__Get := "Getter"
y._NewEnum := "Enumerator"
y.__Call := "Caller"
for k, v in y
MsgBox, %k%: %v%
class SafeObj
{
static Key := {} ; Unique key for internal data.
__New()
{
ObjRawSet(this, SafeObj.Key, {})
}
__Set(k, v)
{
ObjRawSet(this[SafeObj.Key], k, v)
return v
}
_NewEnum()
{
return ObjNewEnum(this[SafeObj.Key])
}
__Get(k)
{
return this[SafeObj.Key, k]
}
}
Re: JSON 2.0 (and Jxon) - JSON lib for AutoHotkey
Updated to v2.0, main post has been updated to reflect changes. Changed interface to mimic JavaScript's JSON.parse() and JSON.stringify(). This update affects the class version only.
Changes:
Changes:
- Removed backward support for old Parse() and Stringify() methods
- Removed JSON.Object and JSON.Array objects
- Removed JSON.Load()'s jsonize paramter
- Added reviver parameter to JSON.Load()
- Added replacer parameter to JSON.Dump()
- Improved handling of array(s) during stringification process
- Limit indentation(pretty-printing) to 10 characters
- Added missing error message
- Disable / escaping when stringifying
Re: JSON 2.0 (and Jxon) - JSON lib for AutoHotkey
Coco, I submitted a pull request to your repo with a small fix that makes it compatible with AHK_H.
AHK_H supports a null type, so I just renamed your null var to _null
In regards to the new stringify changes, two thumbs up - way up!!
I haven't totally got my head around usage of the replacer, but it appears to satisfy my earlier request for a way of filtering out certain keys - and appears to be capable of a whole lot more.
AHK_H supports a null type, so I just renamed your null var to _null
In regards to the new stringify changes, two thumbs up - way up!!
I haven't totally got my head around usage of the replacer, but it appears to satisfy my earlier request for a way of filtering out certain keys - and appears to be capable of a whole lot more.
Return to “Scripts and Functions (v1)”
Who is online
Users browsing this forum: hiahkforum and 39 guests