Code: Select all
#SingleInstance force
class json { ;json.set by vvhitevvizard. json.get by coco and modified by vvhitevvizard
get(ByRef _s) { ;obj:=json.get(str)
static M:=0x7FFFFFFF, q:=Chr(34), p:={"__Arr":1}, x:=q "{[0123456789-" ;json allowed chars outside strings
n:=0, k:="", kf:=0, s:=[root:={}], z:="{"
while (c:=SubStr(_s, ++n, 1)) !== ""
InStr(" `t`n`r", c) || (
InStr(z, c) || E(c, n), a:=(b:=s.1).__Arr, u:=0
, InStr("}]", c) ? ((s.1==root) && E(c, n), s.RemoveAt(1), z:=s.1.__Arr ? ",]" : ",}")
: InStr(",:", c) ? (z:=(kf:=!a && c==",") ? q : x)
: InStr("{[", c) ? ((c=="{") ? (kf:=1, v:={}, z:=q "}")
: (v:=new p, z:=x "]"), s.InsertAt(1,v), a ? k:=b.Push(v) : b[k]:=v)
: ((c==q) ? (v:=SubStr(_s, n+1, InStr(_s,q,, n+1)-n-1)
, n+=StrLen(v)+1, (kf) && (k:=v, z:=":", u:=1)) ;string literals
: (v:=SubStr(_s, n, min(InStr(_s,"]",,n)||M,InStr(_s,"}",,n)||M,InStr(_s,",",,n)||M,InStr(_s," ",,n)||M)-n)
, n+=StrLen(v)-1, (v is "Number") ? v+=0:E(c, n)) ;number
,(u) || (a ? k:=b.Push(v) : b[k]:=v, z:=a ? ",]" : ",}"))
)
return (s.1==root || E(c, n), b) ;s.Count()!=1 ;unpaired {}, []
E(_c,_n)=>this.fthrow(Exception("Unexpected char <" _c "> in pos " _n, -2))
}
static Compact:=0, Space:=4, ErrObjType:=0, ErrObj:=0
set(_o, _d:="") { ;_d:current indent
static q:= Chr(34), ind, space
if !IsObject(_o) ;"string" | number
return this.ErrObj && this.fthrow(Exception("Not an object.", -1))
(_d || space == this.Space) || ind := indent(space := this.Space)
,(this.Compact) ? n:=d:="" : n:="`n", d:=_d ind
,VarSetCapacity(s,1024*8)
try a:=_o.__Arr ;trying to get a unique key
catch ;"Unknown property" exception means its a built-in inenumerable object
return (
t:=Type(_o) " Object"
,(this.ErrObjType) && this.fthrow(Exception(t " type is not supported.", -1))
,"{" q t q "}"
)
for i in _o ;due to the use of a for-loop, arrays such as '[1,,3]' are detected as objects({})
if !(a:=i=A_Index) ;a=0:associative or sparse array ([1,,3])
break
for k, v in _o ;recursive ;JSON standard: keys are always "strings", values r: number|"string"|{object}|[array]
s .= d (a ? "" : q k q ":") (isObject(v) ? this.set(v, d)
: (Type(v)=="String") ? q v q
: (Type(v)=="Float") ? format("{:g}", v) : v) "," n
return (a ? "[" : "{") (s ? (n RTrim(s, "," n) n _d) : "") (a ? "]" : "}") ;wrap to brackets
indent(n) => n ? indent(--n) " " : ""
}
fthrow(e) {
throw e
}
}
; Test runs
j:='{"r1":{"r2":{"type1":11,"type2":11},"misc":12}, "type":"ask","price":104.2,"amount":101, "a":[111,"aa"]}'
t:=A_TickCount
loop(20000)
b:=json.get(j)
a1:=A_TickCount-t
t:=A_TickCount
loop(20000)
s:=json.set(b)
a2:=A_TickCount-t
msgbox(clipboard:=a1 "|" a2 "`n`n" s)