 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Titan
Joined: 11 Aug 2004 Posts: 4975 Location: /b/
|
Posted: Mon Aug 11, 2008 2:15 pm Post subject: JSON read/write parser |
|
|
I wrote this to help with automated hacking of my xulrunner/prism code. Others may also find it useful as a faster and more compact alternative to XML or INI.
| Code: | ; JSON string:
j = {"version":"1","window":{"state":3,"screenX":25,"screenY":25,"width":790,"height":605,"test":{"nested":"object"}},"sidebar":{"visible":false,"width":"200"}}
MsgBox, % json(j, "version") ; returns "1"
MsgBox, % json(j, "window.width", 800) ; returns 790, sets window->width to 800
r = { "a" : true, "b" : [ 1, [ 2.1, 2.2, { "sub" : false, "test" : [ null, "pass" ] } ], 3 ] }
MsgBox, % json(r, "b[1][2].test[1]") ; array support |
Download _________________

Last edited by Titan on Fri Sep 18, 2009 4:03 am; edited 5 times in total |
|
| Back to top |
|
 |
heresy
Joined: 11 Mar 2008 Posts: 291
|
Posted: Mon Aug 11, 2008 3:51 pm Post subject: |
|
|
it reminds me Python's dictionary data type too. good for handling large variables.
i think it would be comfortable if we can skip first parameter and it creates a global variable automatically.
which would look like below
| Code: | json("Screen.Width", A_ScreenWidth) ;set
MsgBox % ("Screen.Width") ;get |
Thanks for sharing _________________ Easy WinAPI - Dive into Windows API World
Benchmark your AutoHotkey skills at PlayAHK.com |
|
| Back to top |
|
 |
n-l-i-d Guest
|
Posted: Mon Aug 11, 2008 4:38 pm Post subject: |
|
|
Impressive!  |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 4975 Location: /b/
|
Posted: Tue Aug 12, 2008 11:10 am Post subject: |
|
|
| heresy wrote: | | i think it would be comfortable if we can skip first parameter and it creates a global variable automatically | Good idea, you can use static variable too. The main version will stay the same so you can modify external objects. _________________
 |
|
| Back to top |
|
 |
haichen
Joined: 05 Feb 2007 Posts: 174 Location: Osnabrück, Germany
|
Posted: Wed Sep 10, 2008 4:33 pm Post subject: |
|
|
There is a problem with spaces after the :.
Would be nice if you (or someone else) could include this.
I tried to figure the problem and I think if there is Whitespace after : z is too small. But the RegexMatch with backreferences ist to complicated for me.
edit: Forgot to say: there's only a problem when changing values like ..."width": 790,...
Thanks for this nice piece of code. |
|
| Back to top |
|
 |
BIG_RED_TEXT
Joined: 12 Jan 2008 Posts: 129
|
Posted: Wed Sep 10, 2008 8:50 pm Post subject: |
|
|
| it seems to be a kickass function imho, think I'll use it |
|
| Back to top |
|
 |
haichen
Joined: 05 Feb 2007 Posts: 174 Location: Osnabrück, Germany
|
Posted: Thu Sep 11, 2008 12:45 am Post subject: |
|
|
I changed the function a little bit. Now it works with structured json files and with spaces after the :.
| Code: | json(ByRef js, s, v = "") {
j = %js%
Loop, Parse, s, .
{
p = 2
RegExMatch(A_LoopField, "([+\-]?)([^[]+)(?:\[(\d+)\])?", q), q3 := q3 ? q3 : 0
Loop {
If (!p := RegExMatch(j, "(""|')([^\1]+?)\1\s*:\s*((""|')?[^\4]*?\4|(\{(?:[^{}]*+|(?5))*\})|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
Return
Else If (-1 == q3 -= x2 == q2 or q2 == "*") {
j = %x3%
z += p + StrLen(x2) - 2
Break
}
Else p += StrLen(x)
}
}
z-=StrLen(x)
If (v !="" ) {
NewStr := RegExReplace(x, x3 , v)
js := RegExReplace(js, x , NewStr,"",1,z)
}
Return, x3 == "false" ? 0 : x3 == "true" ? 1 : x3 == "null" or x3 == "nul" ? "" : SubStr(x3, 1, 1) == "" ? SubStr(x3, 2, -1) : x3
} |
Example:
| Code: | j=
(
{
"intl": {
"app_locale": "de"
},
"options_window": {
"last_tab_index": "2"
}
}
)
test="1212"
MsgBox, % json(j,"options_window.last_tab_index", test)
MsgBox, % json(j,"options_window.last_tab_index") |
|
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 4975 Location: /b/
|
Posted: Thu Sep 11, 2008 10:35 am Post subject: |
|
|
| haichen wrote: | | I changed the function a little bit. Now it works with structured json files and with spaces after the :. | Thanks for writing a fix. This function is not standards compliant with array handling, the wildcard selector is also a custom extension. I had planned to release a fully conformant update but left AutoHotkey to use C# in my toolchain for which I wrote SimpleJSON. I'll look at the ahk code again tonight and will try to make the final adjustments. _________________
 |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 4975 Location: /b/
|
Posted: Thu Sep 11, 2008 9:46 pm Post subject: |
|
|
For those who are interested version 2a is what I currently use. It includes a few bug fixes and supports complex nested arrays:
| Code: | j = { "a" : true, "b" : [ 1, [ 2.1, 2.2, { "sub" : false, "test" : [ null, "pass" ] } ], 3 ] }
MsgBox, % json(j, "b[1][2].test[1]") |
The only problem is an odd quirk in pcre which causes a failure to match {"v":"1"} where "1" could be any one or two digit number, with or without quotes. I think this is due to conflicting atomic alternations; if anyone can write better regex please post them. _________________
 |
|
| Back to top |
|
 |
Rabiator
Joined: 17 Apr 2005 Posts: 283 Location: Sauerland
|
Posted: Thu Sep 11, 2008 10:04 pm Post subject: |
|
|
| Unfortunately the example in your first post doesn't work any more. |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 4975 Location: /b/
|
Posted: Thu Sep 11, 2008 10:55 pm Post subject: |
|
|
| Rabiator wrote: | | Unfortunately the example in your first post doesn't work any more. | Yes, v2 has a bug I previously mentioned - notice "version":"1" in the example and "last_tab_index": "\"1212\"" haichens code. _________________
 |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4367 Location: Qld, Australia
|
Posted: Sun Dec 21, 2008 10:33 am Post subject: |
|
|
| Titan wrote: | | The only problem is an odd quirk in pcre which causes a failure to match {"v":"1"} where "1" could be any one or two digit number, with or without quotes. | Has this been fixed? I see no such problem, but it does fail to match any quoted string containing the character 1. What is the purpose of the 1 in the highlighted character classes below?
| Code: | If (!p := RegExMatch(j, "(?<!\\)(""|')([^\-1]+?)(?<!\\)(?-1)\s*:\s*((\{(?:[^{}]++|(?-1))*\})|(\[(?:[^[\]]++|(?-1))*\])|"
. "(?<!\\)(""|')[^\-1]*?(?<!\\)(?-1)|[+\-]?\d+(?:\.\d*)?|true|false|null?)\s*(?:,|$|\})", x, p))
|
|
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 4975 Location: /b/
|
Posted: Sun Dec 21, 2008 11:16 am Post subject: |
|
|
| Lexikos wrote: | | it does fail to match any quoted string containing the character 1. | After some testing I came to the same conclusion, perhaps I didn't check well enough when I made my earlier claim.
| Lexikos wrote: | | What is the purpose of the 1 in the highlighted character classes below? ... [^\-1] | \-1 is a relative reference to a captured subpattern - see SUBPATTERNS AS SUBROUTINES in pcre(3). I replaced the relative references with absolute ones to work around the bug and the parser works! Thanks for drawing my attention to this.
Version 2 has been committed to the SVN. The old version can be downloaded for historic reasons. _________________
 |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4367 Location: Qld, Australia
|
Posted: Sun Dec 21, 2008 1:06 pm Post subject: |
|
|
| Titan wrote: | | \-1 is a relative reference to a captured subpattern | I believe that is incorrect.
| pcre(3) wrote: | BACKREFERENCES
\n reference by number (can be ambiguous)
\gn reference by number
\g{n} reference by number
\g{-n} relative reference by number
\k<name> reference by name (Perl)
\k'name' reference by name (Perl)
\g{name} reference by name (Perl)
\k{name} reference by name (.NET)
(?P=name) reference by name (Python)
|
Anyway, thanks for the prompt update.
Another thing... should ' be equivalent to "?
- "string' is valid, but doesn't seem like it should be. Using \g{-1} instead of (?-1) would invalidate it.
- Using "string", both " are omitted from the return value.
- Using 'string', both ' are included in the return value.
- Using "string', both are omitted.
- Using 'string", both are kept.
|
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 4975 Location: /b/
|
Posted: Sun Dec 21, 2008 2:01 pm Post subject: |
|
|
| Lexikos wrote: | | \g{-n} relative reference by number | I must have missed that when converting (?-1) to a character class.
| Lexikos wrote: | | should ' be equivalent to "? | No, JSON doesn't define ' as a string token, only ". This is just a quirk in my parser - (""|') isn't matched up with SubStr(j, 1, 1) == """" on line 55 for performance reasons. _________________
 |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|