3 Star 18 Fork 5

天黑请闭眼/ahk2_lib

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
JSON.ahk 7.21 KB
一键复制 编辑 原始数据 按行查看 历史
天黑请闭眼 提交于 2024-04-30 21:03 . Fixed JSON parsing error
/************************************************************************
* @description: JSON格式字符串序列化和反序列化, 修改自[HotKeyIt/Yaml](https://github.com/HotKeyIt/Yaml)
* 增加了对true/false/null类型的支持, 保留了数值的类型
* @author thqby, HotKeyIt
* @date 2024/02/24
* @version 1.0.7
***********************************************************************/
class JSON {
static null := ComValue(1, 0), true := ComValue(0xB, 1), false := ComValue(0xB, 0)
/**
* Converts a AutoHotkey Object Notation JSON string into an object.
* @param text A valid JSON string.
* @param keepbooltype convert true/false/null to JSON.true / JSON.false / JSON.null where it's true, otherwise 1 / 0 / ''
* @param as_map object literals are converted to map, otherwise to object
*/
static parse(text, keepbooltype := false, as_map := true) {
keepbooltype ? (_true := this.true, _false := this.false, _null := this.null) : (_true := true, _false := false, _null := "")
as_map ? (map_set := (maptype := Map).Prototype.Set) : (map_set := (obj, key, val) => obj.%key% := val, maptype := Object)
NQ := "", LF := "", LP := 0, P := "", R := ""
D := [C := (A := InStr(text := LTrim(text, " `t`r`n"), "[") = 1) ? [] : maptype()], text := LTrim(SubStr(text, 2), " `t`r`n"), L := 1, N := 0, V := K := "", J := C, !(Q := InStr(text, '"') != 1) ? text := LTrim(text, '"') : ""
Loop Parse text, '"' {
Q := NQ ? 1 : !Q
NQ := Q && RegExMatch(A_LoopField, '(^|[^\\])(\\\\)*\\$')
if !Q {
if (t := Trim(A_LoopField, " `t`r`n")) = "," || (t = ":" && V := 1)
continue
else if t && (InStr("{[]},:", SubStr(t, 1, 1)) || A && RegExMatch(t, "m)^(null|false|true|-?\d+(\.\d*(e[-+]\d+)?)?)\s*[,}\]\r\n]")) {
Loop Parse t {
if N && N--
continue
if InStr("`n`r `t", A_LoopField)
continue
else if InStr("{[", A_LoopField) {
if !A && !V
throw Error("Malformed JSON - missing key.", 0, t)
C := A_LoopField = "[" ? [] : maptype(), A ? D[L].Push(C) : map_set(D[L], K, C), D.Has(++L) ? D[L] := C : D.Push(C), V := "", A := Type(C) = "Array"
continue
} else if InStr("]}", A_LoopField) {
if !A && V
throw Error("Malformed JSON - missing value.", 0, t)
else if L = 0
throw Error("Malformed JSON - to many closing brackets.", 0, t)
else C := --L = 0 ? "" : D[L], A := Type(C) = "Array"
} else if !(InStr(" `t`r,", A_LoopField) || (A_LoopField = ":" && V := 1)) {
if RegExMatch(SubStr(t, A_Index), "m)^(null|false|true|-?\d+(\.\d*(e[-+]\d+)?)?)\s*[,}\]\r\n]", &R) && (N := R.Len(0) - 2, R := R.1, 1) {
if A
C.Push(R = "null" ? _null : R = "true" ? _true : R = "false" ? _false : IsNumber(R) ? R + 0 : R)
else if V
map_set(C, K, R = "null" ? _null : R = "true" ? _true : R = "false" ? _false : IsNumber(R) ? R + 0 : R), K := V := ""
else throw Error("Malformed JSON - missing key.", 0, t)
} else {
; Added support for comments without '"'
if A_LoopField == '/' {
nt := SubStr(t, A_Index + 1, 1), N := 0
if nt == '/' {
if nt := InStr(t, '`n', , A_Index + 2)
N := nt - A_Index - 1
} else if nt == '*' {
if nt := InStr(t, '*/', , A_Index + 2)
N := nt + 1 - A_Index
} else nt := 0
if N
continue
}
throw Error("Malformed JSON - unrecognized character.", 0, A_LoopField " in " t)
}
}
}
} else if A || InStr(t, ':') > 1
throw Error("Malformed JSON - unrecognized character.", 0, SubStr(t, 1, 1) " in " t)
} else if NQ && (P .= A_LoopField '"', 1)
continue
else if A
LF := P A_LoopField, C.Push(InStr(LF, "\") ? UC(LF) : LF), P := ""
else if V
LF := P A_LoopField, map_set(C, K, InStr(LF, "\") ? UC(LF) : LF), K := V := P := ""
else
LF := P A_LoopField, K := InStr(LF, "\") ? UC(LF) : LF, P := ""
}
return J
UC(S, e := 1) {
static m := Map('"', '"', "a", "`a", "b", "`b", "t", "`t", "n", "`n", "v", "`v", "f", "`f", "r", "`r")
local v := ""
Loop Parse S, "\"
if !((e := !e) && A_LoopField = "" ? v .= "\" : !e ? (v .= A_LoopField, 1) : 0)
v .= (t := m.Get(SubStr(A_LoopField, 1, 1), 0)) ? t SubStr(A_LoopField, 2) :
(t := RegExMatch(A_LoopField, "i)^(u[\da-f]{4}|x[\da-f]{2})\K")) ?
Chr("0x" SubStr(A_LoopField, 2, t - 2)) SubStr(A_LoopField, t) : "\" A_LoopField,
e := A_LoopField = "" ? e : !e
return v
}
}
/**
* Converts a AutoHotkey Array/Map/Object to a Object Notation JSON string.
* @param obj A AutoHotkey value, usually an object or array or map, to be converted.
* @param expandlevel The level of JSON string need to expand, by default expand all.
* @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
*/
static stringify(obj, expandlevel := unset, space := " ") {
expandlevel := IsSet(expandlevel) ? Abs(expandlevel) : 10000000
return Trim(CO(obj, expandlevel))
CO(O, J := 0, R := 0, Q := 0) {
static M1 := "{", M2 := "}", S1 := "[", S2 := "]", N := "`n", C := ",", S := "- ", E := "", K := ":"
if (OT := Type(O)) = "Array" {
D := !R ? S1 : ""
for key, value in O {
F := (VT := Type(value)) = "Array" ? "S" : InStr("Map,Object", VT) ? "M" : E
Z := VT = "Array" && value.Length = 0 ? "[]" : ((VT = "Map" && value.count = 0) || (VT = "Object" && ObjOwnPropCount(value) = 0)) ? "{}" : ""
D .= (J > R ? "`n" CL(R + 2) : "") (F ? (%F%1 (Z ? "" : CO(value, J, R + 1, F)) %F%2) : ES(value)) (OT = "Array" && O.Length = A_Index ? E : C)
}
} else {
D := !R ? M1 : ""
for key, value in (OT := Type(O)) = "Map" ? (Y := 1, O) : (Y := 0, O.OwnProps()) {
F := (VT := Type(value)) = "Array" ? "S" : InStr("Map,Object", VT) ? "M" : E
Z := VT = "Array" && value.Length = 0 ? "[]" : ((VT = "Map" && value.count = 0) || (VT = "Object" && ObjOwnPropCount(value) = 0)) ? "{}" : ""
D .= (J > R ? "`n" CL(R + 2) : "") (Q = "S" && A_Index = 1 ? M1 : E) ES(key) K (F ? (%F%1 (Z ? "" : CO(value, J, R + 1, F)) %F%2) : ES(value)) (Q = "S" && A_Index = (Y ? O.count : ObjOwnPropCount(O)) ? M2 : E) (J != 0 || R ? (A_Index = (Y ? O.count : ObjOwnPropCount(O)) ? E : C) : E)
if J = 0 && !R
D .= (A_Index < (Y ? O.count : ObjOwnPropCount(O)) ? C : E)
}
}
if J > R
D .= "`n" CL(R + 1)
if R = 0
D := RegExReplace(D, "^\R+") (OT = "Array" ? S2 : M2)
return D
}
ES(S) {
switch Type(S) {
case "Float":
if (v := '', d := InStr(S, 'e'))
v := SubStr(S, d), S := SubStr(S, 1, d - 1)
if ((StrLen(S) > 17) && (d := RegExMatch(S, "(99999+|00000+)\d{0,3}$")))
S := Round(S, Max(1, d - InStr(S, ".") - 1))
return S v
case "Integer":
return S
case "String":
S := StrReplace(S, "\", "\\")
S := StrReplace(S, "`t", "\t")
S := StrReplace(S, "`r", "\r")
S := StrReplace(S, "`n", "\n")
S := StrReplace(S, "`b", "\b")
S := StrReplace(S, "`f", "\f")
S := StrReplace(S, "`v", "\v")
S := StrReplace(S, '"', '\"')
return '"' S '"'
default:
return S == this.true ? "true" : S == this.false ? "false" : "null"
}
}
CL(i) {
Loop (s := "", space ? i - 1 : 0)
s .= space
return s
}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
AutoHotkey
1
https://gitee.com/orz707/ahk2_lib.git
git@gitee.com:orz707/ahk2_lib.git
orz707
ahk2_lib
ahk2_lib
master

搜索帮助

23e8dbc6 1850385 7e0993f3 1850385