Jump to content

Recommended Posts

Posted

#Include "Json.au3"

Local $Json = '{ "Headers":[ { "Name":"LOGICAL_NAME","Type":"VARCHAR2"}],"ColumnCount":1,"Rows":[ { "Cells":[ "ThisIsWhatIWant"],"CellCount":1}]}'
Local $Obj = Json_Decode($Json)

ConsoleWrite(Json_Get($Obj, '["Rows"][0]["Cells"][0]') & @LF)
ConsoleWrite(Json_Get($Obj, '.Rows[0].Cells[0]') & @LF)

ConsoleWrite(Json_Encode($Obj, $JSON_PRETTY_PRINT) & @LF)

新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Posted (edited)

I'm learning JSON, so I wanted a ConsoleWriteJson( $StringJson ) , so I put it together, it may help the next guy ( you'd need to #include <JSON.au3> , but you know that. )

Edit1: I see I did not code anything in case of error.

Func ConsoleWriteJson($sJsonString, $sDesc = "", $iEcho = True)
    If $sDesc = "" Then $sDesc = 'ConsoleWriteJson'
    Local $obj = Json_Decode($sJsonString)
    Local $sOutGlobal = ""
    Return Json_Iterate($obj, '', $sOutGlobal, $sDesc, $iEcho)
EndFunc   ;==>ConsoleWriteJson

Func Json_Iterate($obj, $String, ByRef $sOutGlobal, $pre = "", $iEcho = True)
    Local $sOut = ""
    Local $temp, $i, $b
    If ($pre <> "") Then
        $sOutGlobal &= $pre & ": "
        If $iEcho Then ConsoleWrite($pre & ": ")
    EndIf
    $a = Json_Get_ShowResult($obj, $String, $sOutGlobal, $iEcho)
    If IsArray($a) Then
        For $i = 0 To UBound($a) - 1
            Json_Iterate($obj, $String & '[' & $i & ']', $sOutGlobal, $pre, $iEcho)
        Next
    ElseIf IsObj($a) Then
        $b = Json_ObjGetKeys($a)
        For $temp In $b
            Json_Iterate($obj, $String & '["' & $temp & '"]', $sOutGlobal, $pre, $iEcho)
        Next
    EndIf
    Return $sOutGlobal
EndFunc   ;==>Json_Iterate

Func Json_Get_ShowResult($Var, $Key, ByRef $sOutGlobal, $iEcho)
    Local $sOut = ""
    Local $Ret = Json_Getr($Var, $Key)
    If @error Then
        Switch @error
            Case 1
                $sOut &= "Error 1: key not exists" & @LF
                $sOutGlobal &= $sOut
                If $iEcho Then ConsoleWrite($sOut)
            Case 2
                $sOut &= "Error 2: syntax error" & @LF
                $sOutGlobal &= $sOut
                If $iEcho Then ConsoleWrite($sOut)
        EndSwitch
    Else
        $sOut &= $Key & " => " & VarGetType($Ret) & ": " & $Ret & @LF
        $sOutGlobal &= $sOut
        If $iEcho Then ConsoleWrite($sOut)
    EndIf
    Return $Ret
EndFunc   ;==>Json_Get_ShowResult

Func Json_Getr($Var, $Key)
    If Not $Key Then Return $Var
    Local $Match = StringRegExp($Key, "(^\[([^\]]+)\])", 3)
    If IsArray($Match) Then
        Local $Index = Json_Decode($Match[1])
        $Key = StringTrimLeft($Key, StringLen($Match[0]))
        If IsString($Index) And Json_IsObject($Var) And Json_ObjExists($Var, $Index) Then
            Local $Ret = Json_Getr(Json_ObjGet($Var, $Index), $Key)
            Return SetError(@error, 0, $Ret)
        ElseIf IsNumber($Index) And IsArray($Var) And $Index >= 0 And $Index < UBound($Var) Then
            Local $Ret = Json_Getr($Var[$Index], $Key)
            Return SetError(@error, 0, $Ret)
        Else
            Return SetError(1, 0, "")
        EndIf
    EndIf
    Return SetError(2, 0, "")
EndFunc   ;==>Json_Getr
Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

  • 3 months later...
  • 3 weeks later...
Posted

Thank you Ward for the time invested in this UDF, because I really do not understand the whole JSON thing yet :sweating:, so I am thankfull you do ;-)

I wanted to change some settings in the Chrome preferences-file, which turnout to be a JSON-file, so I am going to use your UDF! :) 

  • 2 months later...
Posted (edited)

Hello,

It seems that having ExpandVarStrings or ExpandEnvStrings option set to 1 makes Json_encode() function crashes. I have to do this in order to make the function works :      

Opt("ExpandVarStrings",0)
Opt("ExpandEnvStrings",0)
Json_Encode($obj,$JSON_UNESCAPED_SLASHES))
Opt("ExpandVarStrings",1)
Opt("ExpandEnvStrings",1)

Otherwise the program simply crashes ( There is no AutoIT error, the program just crashes ). Are you aware of this possible bug ?

Regards. 

Edited by Xplode
  • 2 months later...
Posted

Ahh... working with JSON is so much easier tolerable now, thanks to you Ward!

I'm so glad I found this UDF!!

  • 3 weeks later...
Posted (edited)

How do I list the last level of objects in the last level of keys?  As you can see I've commented out my last, of many, efforts.

 

#include "Json.au3"

$Json = '{"Air Elemental":{"layout":"normal","name":"Air Elemental","manaCost":"{3}{U}{U}","cmc":5,"colors":["Blue"],"type":"Creature — Elemental","types":["Creature"],"subtypes":["Elemental"],"text":"Flying","power":"4","toughness":"4","imageName":"air elemental","colorIdentity":["U"]},"Ancestral Recall":{"layout":"normal","name":"Ancestral Recall","manaCost":"{U}","cmc":1,"colors":["Blue"],"type":"Instant","types":["Instant"],"text":"Target player draws three cards.","imageName":"ancestral recall","colorIdentity":["U"]}'


$Obj = Json_Decode($Json)


If Json_IsObject($Obj) Then
    $Keys = Json_ObjGetKeys($Obj)
    For $i = 0 To UBound($Keys) - 1
        ConsoleWrite($Keys[$i] & @LF)

        $obects = Json_ObjGet($Obj, $Keys[$i])
        $KeysB = Json_ObjGetKeys($obects)

        For $h = 0 To UBound($KeysB) - 1
            ConsoleWrite('  ' & $KeysB[$h] & @LF)

;~          $obectsB = Json_ObjGet($obects, $KeysB[$h])
;~          $KeysC = Json_ObjGetKeys($obectsB)

;~          For $g = 0 To UBound($KeysC) - 1
;~              ConsoleWrite('      ' &  $KeysC[$g] & @LF)
;~          Next

        Next
    Next
EndIf

 

Edited by Jury
Posted (edited)

How do I list the last level of objects in the last level of keys?

according to http://stackoverflow.com/questions/4317456/getting-the-last-item-in-a-javascript-object

No. Order is not guaranteed in JSON and most other key-value data structures, 
so therefore the last item could sometimes be carrot and
at other times be banana and so on. If you need to rely on ordering, 
your best bet is to go with arrays. 
The power of key-value data structures lies in accessing values by
their keys, not in being able to get the nth item of the object.

or play around with ConsoleWriteJson  https://www.autoitscript.com/forum/topic/148114-a-non-strict-json-udf-jsmn/?do=findComment&comment=1224189  above

Edit: I see that the string has game like values and if it's a bot, I just got me in trouble for helping, but you've been here since 2009 and would not even dream of that.

Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

Hello.
I wonder if there is a quick way to get key knowing only the array element.
Here is JSON string:

{"result":{"tree":{"36":{"1958":[989,1649,2066,659,616]},"4":{"2317":[886,2350,2219,1520,795,1352,809,2521],"1960":[2197,1628,1538,2332,1416],"489":[1277],"1289":[2213,25,2105,2214]},"34":{"2354":[1271],"2362":[1265,1266,1267,1358,2363,1268,1673,1269,1270,1275,2364,1276,1274],"1264":[2358,2359,2360,2361],"2057":[2355,2474,2356,2357],"2413":[1501,1580,525]},"10":{"610":[628,1568,1542,2335,1544,1545,1546,1549,1597,1552,1550,1553,1554,617,1555,2017,1257,1258,2208,677,1255,1479,1261,614,1259,2065,1254,1260,2209,2210,1547,1548,2211,615],"1581":[1582,1583,1590,1587,1594,1591,1588,1596,1585,1586,2078,1929,1593,1592,1595],"1556":[1557,1560,1561,1653,1570,1654,1655,1656,1930,1931,1932,1562,1563,1626,1564,1565,1559,1566,1573,1567]},"33":{"395":[396,2322,2167,1993,2321],"2326":[1036,400,574],"2389":[2387,2388],"2327":[695,399,402,490,499],"2324":[2325,2342,530,2152],"2328":[403,1279,716,2165,401]}}}}

I know only array element, for example, 1583. I need to get key - 10

Here is how I do that for now:

#Include <Array.au3>
#Include <Json.au3> ; https://www.autoitscript.com/forum/topic/148114-a-non-strict-json-udf-jsmn/

$iForumID = 1583
$sJSON = '{"result":{"tree":{"36":{"1958":[989,1649,2066,659,616]},"4":{"2317":[886,2350,2219,1520,795,1352,809,2521],"1960":[2197,1628,1538,2332,1416],"489":[1277],"1289":[2213,25,2105,2214]},"34":{"2354":[1271],"2362":[1265,1266,1267,1358,2363,1268,1673,1269,1270,1275,2364,1276,1274],"1264":[2358,2359,2360,2361],"2057":[2355,2474,2356,2357],"2413":[1501,1580,525]},"10":{"610":[628,1568,1542,2335,1544,1545,1546,1549,1597,1552,1550,1553,1554,617,1555,2017,1257,1258,2208,677,1255,1479,1261,614,1259,2065,1254,1260,2209,2210,1547,1548,2211,615],"1581":[1582,1583,1590,1587,1594,1591,1588,1596,1585,1586,2078,1929,1593,1592,1595],"1556":[1557,1560,1561,1653,1570,1654,1655,1656,1930,1931,1932,1562,1563,1626,1564,1565,1559,1566,1573,1567]},"33":{"395":[396,2322,2167,1993,2321],"2326":[1036,400,574],"2389":[2387,2388],"2327":[695,399,402,490,499],"2324":[2325,2342,530,2152],"2328":[403,1279,716,2165,401]}}}}'

ConsoleWrite (_GetAPICategoryID ($iForumID) & @CRLF)


Func _GetAPICategoryID ($iffAPIForumID)
    $Obj = Json_ObjGet(Json_ObjGet(Json_Decode($sJSON), "result"), "tree")
    $aTMP15 = Json_ObjGetKeys ($Obj)
    $iFoundCategoryID = ""
    For $i = 0 To UBound ($aTMP15) -1
        $Obj1 = Json_ObjGet ($Obj, $aTMP15[$i])
        $aTMP16 = Json_ObjGetKeys ($Obj1)
            For $x = 0 To UBound ($aTMP16) -1
                $aTMP17 = Json_Get ($Obj1, '["' & $atmp16[$x] & '"]')
                If _ArraySearch ($aTMP17, $iffAPIForumID) <> -1 Then
                    $iFoundCategoryID = $aTMP15[$i]
                    ExitLoop
                EndIf
            Next
        If $iFoundCategoryID  <> "" Then ExitLoop
    Next
    Return $iFoundCategoryID
EndFunc ; _GetAPICategoryID ()

But this is too slow and not gracefully. Maybe there is better way? Thank you in advance

  • 5 weeks later...
Posted

Hello. I want to say thank you for this UDF, I tried other, nothing worked. And this figured out thanks to the topic and running. But still faced with the problem and do not know how to do that. I hope will prompt

Have two json

json_1
{"response":{"status":1,"httpStatus":200,"data":[{"id":"10445","categories":{"6":{"id":"6","name":"D"},"27":{"id":"27","name":"I"}}},{"id":"10159","categories":{"20":{"id":"20","name":"W"}}}],"errors":[],"errorMessage":null}}

json_2
{"response":{"status":1,"httpStatus":200,"data":[{"id":"11930","countries":{"CH":{"id":"756","code":"CH","name":"Switzerland","regions":[]}}},{"id":"11928","countries":{"UK":{"id":"826","code":"UK","name":"United Kingdom","regions":[]},"HR":{"id":"191","code":"HR","name":"Croatia","regions":[]}}}],"errors":[],"errorMessage":null}}

from both must be received "name" in the first "categories", the second of the "countries"

my code

#include <Array.au3>
#include "JSON.au3"

$sJSON = FileRead(@ScriptDir & "\1.json")

$objJson = Json_Decode($sJSON)
$Response = Json_ObjGet($objJson, "response")
$Data = Json_ObjGet($Response, "data")
Local $N = UBound($Data)
Dim $List[$N]
    For $i = 0 To UBound($Data) - 1
        Local $objJson2 = $Data[$i]
        Local $Categories = Json_ObjGet($objJson2, "categories") ;or "countries" for json_2
        Local $nCat = Json_ObjGetKeys($Categories)
        Local $N = UBound($nCat)
        Dim $aCat[$N]
        For $j = 0 To UBound($nCat) - 1
            Local $objJson2 = Json_ObjGet($Categories, $nCat[$j])
            $aCat[$j] = Json_ObjGet($objJson2, "name")
        Next
        $strCat = ''
        For $j = 0 to UBound($aCat) - 1
            $strCat &= $aCat[$j] & ', ' 
        Next
        $strCat = StringTrimRight($strCat, 2)
        $List[$i] = $strCat 
     Next

_ArrayDisplay($List,"List")

For json_1 works fine. For json_2 function Json_ObjGetKeys an error

JSON.au3 "(342): ==> Variable must be of type" Object ".:
Return $ Object.Keys ()
Return $ Object ^ ERROR

I realized that the reason for this error is that the structure of "countries" objects letters "CH", "UK" and the like, and the structure of the "categories" - number
How do I get the data from "countries" in this situation?

Posted

@addjon, many ask for an Arrayfied Json. Here is my take at it, that works with your string. ( may not work with others )

#include <JSon.au3>
#include <Array.au3>

Local $sJson_1 = '{"response":{"status":1,"httpStatus":200,"data":[{"id":"10445","categories":{"6":{"id":"6","name":"D"},"27":{"id":"27","name":"I"}}},{"id":"10159","categories":{"20":{"id":"20","name":"W"}}}],"errors":[],"errorMessage":null}}'
Local $sJson_2 = '{"response":{"status":1,"httpStatus":200,"data":[{"id":"11930","countries":{"CH":{"id":"756","code":"CH","name":"Switzerland","regions":[]}}},{"id":"11928","countries":{"UK":{"id":"826","code":"UK","name":"United Kingdom","regions":[]},"HR":{"id":"191","code":"HR","name":"Croatia","regions":[]}}}],"errors":[],"errorMessage":null}}'

Local $aReturned = JsonArrayfied($sJson_1)
_ArrayDisplay($aReturned, "$aReturned")

$aReturned = JsonArrayfied($sJson_2)
_ArrayDisplay($aReturned, "$aReturned")

Func JsonArrayfied($sJsonString, $iEcho = 0)
    Local $sConsoleWriteJson = ConsoleWriteJson($sJsonString, "", $iEcho)
    Local $n, $aLines = StringSplit($sConsoleWriteJson, @LF, 1)
    Local $aTemp, $iRow = 0, $iCol = 0, $m, $aJsonArrayfied[UBound($aLines) + 1][100] ; a lazy but efficient way to go about it
    For $n = 1 To $aLines[0]
        If StringInStr($aLines[$n], ":") + 2 > StringLen($aLines[$n]) Then ContinueLoop
        $aLines[$n] = StringReplace($aLines[$n], "][", "|")
        $aLines[$n] = StringReplace($aLines[$n], "]", "|")
        $aLines[$n] = StringReplace($aLines[$n], "[", "|")
        $aTemp = StringSplit($aLines[$n], "|")
        $iRow += 1
        For $m = 1 To $aTemp[0] - 1
            If $iCol < $m Then $iCol = $m
            $aJsonArrayfied[$iRow][$m - 1] = StringReplace($aTemp[$m], '"', '')
        Next
        $aJsonArrayfied[$iRow][$aTemp[0] - 1] = StringTrimLeft($aTemp[$aTemp[0]], StringInStr($aTemp[$aTemp[0]], ":") + 1)
        $aJsonArrayfied[$iRow][0] = StringMid($aTemp[$aTemp[0]], 5, StringInStr($aTemp[$aTemp[0]], ":") - 5)
    Next
    $aJsonArrayfied[0][0] = $iRow
    $aJsonArrayfied[0][1] = $iCol
    ReDim $aJsonArrayfied[$iRow + 1][$iCol + 1]
    Return $aJsonArrayfied
EndFunc   ;==>JsonArrayfied

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; added by me

Func ConsoleWriteJson($sJsonString, $sDesc = "", $iEcho = 1)
    Local $sOutGlobal
    If $sDesc = "" Then $sDesc = 'ConsoleWriteJson'
    Local $obj = Json_Decode($sJsonString)
    Json_Iterate($sOutGlobal, $obj, '', $sDesc, $iEcho)
    Return $sOutGlobal
EndFunc   ;==>ConsoleWriteJson

Func Json_Iterate(ByRef $sOutGlobal, $obj, $string, $pre = "", $iEcho = 1)
    Local $sOut = ""
    Local $temp, $i, $b
    If ($pre <> "") Then
        $sOut &= $pre & ": "
        If $iEcho Then ConsoleWrite($pre & ": ")
    EndIf
    $a = Json_Get_ShowResult($obj, $string, $sOutGlobal, $iEcho)
    If IsArray($a) Then
        For $i = 0 To UBound($a) - 1
            Json_Iterate($sOutGlobal, $obj, $string & '[' & $i & ']', $pre, $iEcho)
        Next
    ElseIf IsObj($a) Then
        $b = Json_ObjGetKeys($a)
        For $temp In $b
            Json_Iterate($sOutGlobal, $obj, $string & '["' & $temp & '"]', $pre, $iEcho)
        Next
    EndIf
    Return $sOutGlobal
EndFunc   ;==>Json_Iterate

Func Json_Get_ShowResult($Var, $Key, ByRef $sOutGlobal, $iEcho)
    Local $sOut = ""
    Local $Ret = Json_Getr($Var, $Key)
    If @error Then
        Switch @error
            Case 1
                $sOut &= "Error 1: key not exists" & @LF
                If $iEcho Then ConsoleWrite($sOut)
            Case 2
                $sOut &= "Error 2: syntax error" & @LF
                If $iEcho Then ConsoleWrite($sOut)
        EndSwitch
    Else
        $sOut &= $Key & " => " & VarGetType($Ret) & ": " & $Ret & @LF
        If $iEcho Then ConsoleWrite($sOut)
    EndIf
    $sOutGlobal &= $sOut ;& $Ret
    Return $Ret
EndFunc   ;==>Json_Get_ShowResult

Func Json_Getr($Var, $Key)
    If Not $Key Then Return $Var
    Local $Match = StringRegExp($Key, "(^\[([^\]]+)\])", 3)
    If IsArray($Match) Then
        Local $Index = Json_Decode($Match[1])
        $Key = StringTrimLeft($Key, StringLen($Match[0]))
        If IsString($Index) And Json_IsObject($Var) And Json_ObjExists($Var, $Index) Then
            Local $Ret = Json_Getr(Json_ObjGet($Var, $Index), $Key)
            Return SetError(@error, 0, $Ret)
        ElseIf IsNumber($Index) And IsArray($Var) And $Index >= 0 And $Index < UBound($Var) Then
            Local $Ret = Json_Getr($Var[$Index], $Key)
            Return SetError(@error, 0, $Ret)
        Else
            Return SetError(1, 0, "")
        EndIf
    EndIf
    Return SetError(2, 0, "")
EndFunc   ;==>Json_Getr

Hope it helps to get what you look for.

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

argumentum,

Brilliant!  and here I was attempting to stuff json into an array with little success.  Attached is an example of my data - it takes some time but then the end is an array of over 20,000  lines. So much better and reliable than parsing using regular expressions etc.

Thanks ever so...

cma-cases.json

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...