发表回复 
字符串转对象
2014-10-01, 00 : 46
字符串转对象
目标:符合AHK规则的字符串转对象

我们创建并赋值对象:
f:={Hello:"Hello World", ref:"World"}
这是AHK创建对象的规则,但并不符合JSON规则,正规的JSON字符串应该是:
{"Hello":"Hello World", "ref":"World"}


代码: (全选)
f={"Hello":"Hello`nWorld", "ref":"World", "refd":{"Hello":"Hello`nWorld", "ref":"World", "refd":"1"}}
MsgBox % ObjTree(SerDes(f))
SerDes(src, out:="", indent:="") {

    ;// Begin de-serialization routine
    static is_v2 := (A_AhkVersion >= "2"), q := Chr(34) ;// Double quote
         , push  := Func(is_v2 ? "ObjPush"     : "ObjInsert")
         , ins   := Func(is_v2 ? "ObjInsertAt" : "ObjInsert")
         , set   := Func(is_v2 ? "ObjRawSet"   : "ObjInsert")
         , pop   := Func(is_v2 ? "ObjPop"      : "ObjRemove")
         , del   := Func(is_v2 ? "ObjRemoveAt" : "ObjRemove")
    static esc_seq := { ;// AHK escape sequences
    (Join Q C
        "``": "``",  ;// accent
        (q):  q,     ;// double quote
        "n":  "`n",  ;// newline
        "r":  "`r",  ;// carriage return
        "b":  "`b",  ;// backspace
        "t":  "`t",  ;// tab
        "v":  "`v",  ;// vertical tab
        "a":  "`a",  ;// alert (bell)
        "f":  "`f"   ;// formfeed
    )}

    ;// Extract string literals
    strings := [], i := 0, end := 0-is_v2 ;// v1.1=0, v2.0-a=-1 -> SubStr()
    while (i := InStr(src, q,, i+1)) {
        j := i
        while (j := InStr(src, q,, j+1))
            if (SubStr(str := SubStr(src, i+1, j-i-1), end) != "``")
                break
        if !j
            throw "Missing close quote(s)."
        src := SubStr(src, 1, i) . SubStr(src, j+1)
        k := 0
        while (k := InStr(str, "``",, k+1)) {
            if InStr(q "``nrbtvaf", ch := SubStr(str, k+1, 1))
                str := SubStr(str, 1, k-1) . esc_seq[ch] . SubStr(str, k+2)
            else throw "Invalid escape sequence: '``" . ch . "'"
        }
        strings.Insert(str) ;// strings.Insert(str) / strings.Push(str)
    }
    ;// Begin recursive descent to parse markup
    pos := 0
    , is_key := false ;// if true, active data is to be used as associative array key
    , refs := [], kobj := [] ;// refs=object references, kobj=objects as keys
    , stack := [tree := []]
    , is_arr := Object(tree, 1)
    , next := q "{[01234567890-" ;// chars considered valid when encountered
    while ((ch := SubStr(src, ++pos, 1)) != "") {
        if InStr(" `t`n`r", ch)
            continue
        if !InStr(next, ch) ;// validate current char
            throw "Unexpected char: '" ch "'"
        is_array := is_arr[_obj := stack[1]] ;// active container object
        ;// Associative/Linear array opening
        if InStr("{[", ch) {
            val := {}, is_arr[val] := ch == "[", %push%(refs, &val)
            if is_key
                %ins%(kobj, 1, val), key := val
            is_array? %push%(_obj, val) : %set%(_obj, key, is_key ? 0 : val)
            , %ins%(stack, 1, val), is_key := ch == "{"
            , next := q "{[0123456789-$" (is_key ? "}" : "]") ;// Chr(NumGet(ch, "Char")+2)
        }
        ;// Associative/Linear array closing
        else if InStr("}]", ch) {
            next := is_arr[stack[2]] ? "]," : "},"
            if (kobj[1] == %del%(stack, 1))
                key := %del%(kobj, 1), next := ":"
        }
        ;// Token
        else if InStr(",:", ch) {
            if (_obj == tree)
                throw "Unexpected char: '" ch "' -> there is no container object."
            next := q "{[0123456789-$", is_key := (!is_array && ch == ",")
        }
        ;// String | Number | Object reference
        else {
            if (ch == q) { ;// string
                val := %del%(strings, 1)
            } else { ;// number / object reference
                if (is_ref := (ch == "$")) ;// object reference token
                    pos += 1
                val := SubStr(src, pos, (SubStr(src, pos) ~= "[\]\}:,\s]|$")-1)
                if (Abs(val) == "")
                    throw "Invalid number: " val
                pos += StrLen(val)-1, val += 0
                if is_ref {
                    if !ObjHasKey(refs, val)
                        throw "Invalid object reference: $" val
                    val := Object(refs[val]), is_ref := false
                }
            }
            if is_key
                key := val, next := ":"
            else
                is_array? %push%(_obj, val) : %set%(_obj, key, val)
                , next := is_array ? "]," : "},"
        }
    }
    return tree[1]
}
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
2014-10-01, 10 : 00 (这个帖子最后修改于: 2014-10-01 10 : 09 by robertL.)
RE: 字符串转对象
相关

One for all, but man for himself

帮推广:AHK知乎专栏
查找这个用户的全部帖子
表示感谢 引用并回复 移动视图置页面顶端
发表回复 


论坛跳转:


联系我们 | Autohotkey 中文站 | 回到顶部 | 回到正文区 | 精简(归档)模式 | RSS 聚合