【问题标题】:Json parsing, generating and beautifiying / formatting with AutoHotkey?使用 AutoHotkey 解析、生成和美化/格式化 Json?
【发布时间】:2016-03-03 12:35:22
【问题描述】:

如何将 json 字符串转换为自动热键对象/数组...反之亦然?以及如何使用换行符和空格缩进很好地格式化 json 字符串?

【问题讨论】:

  • 这是一个自我回答的问题!没有理由拒绝它!

标签: json autohotkey code-formatting


【解决方案1】:

这是我最近写的一个 Json 类。它会自动处理缩进和换行符。您甚至可以指定要使用的字符等。
它还处理字符串中的双引号等边缘情况(它们需要在 json 中转义),这是我在 ahk 中的其他 json 函数中真正缺少的东西。

class Json {
    __New(indent="    ",newLine="`r`n") { ;default indent: 4 spaces. default newline: crlf
        this.ind := indent
        this.nl := newLine
    }

    getIndents(num) {
        indents := ""
        Loop % num
            indents .= this.ind
        Return indents
    }

    jsonFileToObj(fileFullPath) {
        file := FileOpen(fileFullPath, "r")
        Return this.jsonToObj(file.Read()), file.Close()
    }

    objToJsonFile(obj,fileFullPath) {
        FileDelete, % fileFullPath
        SplitPath, fileFullPath,, dir
        FileCreateDir % dir
        file := FileOpen(fileFullPath, "w")
        Return file.write(this.objToJson(obj)), file.Close()
    }

    objToJson(obj,indNum:=0) {
        indNum++
        str := "" , array := true
        for k in obj {
            if (k == A_Index)
                continue
            array := false
            break
        }
        for a, b in obj
            str .= this.getIndents(indNum) . (array ? "" : """" a """: ") . (IsObject(b) ? this.objToJson(b,indNum) : this.isNumber(b) ? b : """" StrReplace(b,"""","\""") """") . ", " this.nl
        str := RTrim(str, " ," this.nl)
        return (array ? "[" this.nl str this.nl this.getIndents(indNum-1) "]" : "{" this.nl str this.nl this.getIndents(indNum-1) "}")
    }

    jsonToObj(jsonStr) {
        SC := ComObjCreate("ScriptControl") 
        SC.Language := "JScript"
        ComObjError(false)
        jsCode =
        (
        function arrangeForAhkTraversing(obj) {
            if(obj instanceof Array) {
                for(var i=0 ; i<obj.length ; ++i)
                    obj[i] = arrangeForAhkTraversing(obj[i]) ;
                return ['array',obj] ;
            } else if(obj instanceof Object) {
                var keys = [], values = [] ;
                for(var key in obj) {
                    keys.push(key) ;
                    values.push(arrangeForAhkTraversing(obj[key])) ;
                }
                return ['object',[keys,values]] ;
            } else
                return [typeof obj,obj] ;
        }
        )
        SC.ExecuteStatement(jsCode "; obj=" jsonStr)
        return this.convertJScriptObjToAhkObj( SC.Eval("arrangeForAhkTraversing(obj)") )
    }

    convertJScriptObjToAhkObj(jsObj) {
        if(jsObj[0]="object") {
            obj := {}, keys := jsObj[1][0], values := jsObj[1][1]
            loop % keys.length
                obj[keys[A_INDEX-1]] := this.convertJScriptObjToAhkObj( values[A_INDEX-1] )
            return obj
        } else if(jsObj[0]="array") {
            array := []
            loop % jsObj[1].length
                array.insert(this.convertJScriptObjToAhkObj( jsObj[1][A_INDEX-1] ))
            return array
        } else
            return jsObj[1]
    }

    isNumber(Num) {
        if Num is number
            return true
        else
            return false
    }
}

方法列表:

json.jsonFileToObj(fileFullPath)      ;convert a json file into an ahk object
json.objToJsonFile(obj,fileFullPath)  ;convert an ahk object into a json file

json.objToJson(obj)      ;convert an object into a json string
json.jsonToObj(jsonStr)  ;convert a json string into an ahk object

例子:

json := new Json("  ", "`r`n") ;use 2 space indentation and CR LF for new lines

testObject := {"key":"","key2":"val2",keyWithoutQuotes:"val3","myArray":["a1","a2","a3",{"myEdgeCase":"edge case ""test""","numberValue":2}]}

MsgBox % json.objToJson(testObject)

输出:

{
  "key": "", 
  "key2": "val2", 
  "keyWithoutQuotes": "val3", 
  "myArray": [
    "a1", 
    "a2", 
    "a3", 
    {
      "myEdgeCase": "edge case \"test\"", 
      "numberValue": 2
    }
  ]
}

另外还有Coco's Json Class,你一定要看看。它可能是代码的 4 倍,但它确实有一些有趣的功能。

【讨论】:

    【解决方案2】:

    我使用以下功能,目前为止非常适合我。没有文件处理,而是自己决定方向:

    json(i)
    {
      ;ENCODE
      if (isobject(i))
      {
        o := "", a := 1, x := 1
        for k,v in i
        {
          if (k!=x)
            a := 0, break
          x += 1
        }
        o .= (a) ? "[" : "{", f := 1
        for k,v in i
          o .= ((f) ? "" : ",")((a) ? "" : """" k """:")((isobject(v)) ? json(v) : ((v+0=v) ? v : """" v """")), f := 0
        return o ((a) ? "]" : "}")
      }
      ;DECODE
      if (regexmatch(i, "s)^__chr(A|W):(.*)", m))
      {
        VarSetCapacity(b, 4, 0), NumPut(m2, b, 0, "int")
        return StrGet(&b, 1, (m1="A") ? "cp28591" : "utf-16")
      }
      if (regexmatch(i, "s)^__str:((\\""|[^""])*)", m))
      {
        str := m1
        for p,r in {b:"`b", f:"`f", n:"`n", 0:"", r:"`r", t:"`t", v:"`v", "'":"'", """":"""", "/":"/"}
          str := regexreplace(str, "\\" p, r)
        while (regexmatch(str, "s)^(.*?)\\x([0-9a-fA-F]{2})(.*)", m))
          str := m1 json("__chrA:0x" m2) m3
        while (regexmatch(str, "s)^(.*?)\\u([0-9a-fA-F]{4})(.*)", m))
          str := m1 json("__chrW:0x" m2) m3
        while (regexmatch(str, "s)^(.*?)\\([0-9]{1,3})(.*)", m))
          str := m1 json("__chrA:" m2) m3
        return regexreplace(str, "\\\\", "\")
      }
      str := [], obj := []
      while (RegExMatch(i, "s)^(.*?[^\\])""((\\""|[^""])*?[^\\]|)""(.*)$", m))
        str.insert(json("__str:" m2)), i := m1 "__str<" str.maxIndex() ">" m4
      while (RegExMatch(RegExReplace(i, "\s+", ""), "s)^(.*?)(\{|\[)([^\{\[\]\}]*?)(\}|\])(.*)$", m))
      {
        a := (m2="{") ? 0 : 1, c := m3, i := m1 "__obj<" ((obj.maxIndex()+1) ? obj.maxIndex()+1 : 1) ">" m5, tmp := []
        while (RegExMatch(c, "^(.*?),(.*)$", m))
          tmp.insert(m1), c := m2
        tmp.insert(c), tmp2 := {}, obj.insert(cobj := {})
        for k,v in tmp
        {
          if (RegExMatch(v, "^(.*?):(.*)$", m))
            tmp2[m1] := m2
          else
            tmp2.insert(v)
        }
        for k,v in tmp2
        {
          for x,y in str
            k := RegExReplace(k, "__str<" x ">", y), v := RegExReplace(v, "__str<" x ">", y)
          for x,y in obj
            v := RegExMatch(v, "^__obj<" x ">$") ? y : v
          cobj[k] := v
        }
      }
      return obj[obj.maxIndex()]
    }
    

    source

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-15
      • 2021-03-10
      • 2014-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多