Jump to content
Ward

A Non-Strict JSON UDF (JSMN)

Recommended Posts

Hey,

thanks for the UDF, good work. But I have problems with a specific json source -> http://data.mtgox.com/api/1/BTCUSD/depth

I can't extract the values. First I used the other JSON UDF from Gabriel Boehme and I have exactly the same problems.

I get an empty array with ~500 elements when I get into the asks or bids arrays.

This is what I'm doing to get the data:

Func getArrayFromJson($URI,$reqAuth,$post="")
$result = Jsmn_Decode(goxRequest($URI,_Iif($reqAuth>0,getNonce()&$post,"")))
$result = Jsmn_ObjTo2DArray($result)
If (Not IsArray($result) Or UBound($result) = 0) Then
MsgBox(0,"Error: "&$URI,$result)
Return 0
Else
If(NOT IsArray($result[2][1])) Then
MsgBox(0,$URI,$result[2][1])
Return 0
EndIf
Return $result[2][1]
EndIf
EndFunc

It works on every other API without problems, just not with this one.

Share this post


Link to post
Share on other sites

Try this code, then your will see every element is decoded succeed.

#Include "JSMN.au3"

Local $Json = BinaryToString(InetRead("http://data.mtgox.com/api/1/BTCUSD/depth"), 4)
Local $Obj = Jsmn_Decode($Json)

ConsoleWrite(Jsmn_Encode($Obj, $JSMN_PRETTY_PRINT))

Then why you got empty output?

Because in your code, "$result[2][1]" is an array, so you can't use MsgBox to output it.


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

 

Share this post


Link to post
Share on other sites

Hey Ward,

fist of all thanks for JSON extension! I appreciate the work you spent to help this community with your programming skills!

I am new to this forum and autoit is one of my personal interests so I would like to say "Hello everyone" :bye:.

Maybe someone can help me with my question?:

I want to query a JSON wheather service to get the actual wheater and for future use also the forecast.

For this I use OperWheatherMap API and build my JSON, e.g. for today in Berlin:

{"cod":"200","message":0.0268,"city":{"id":2950159,"name":"Berlin","coord":{"lon":13.41053,"lat":52.524368},"country":"DE","population":1000000},"cnt":1,"list":[{"dt":1368874800,"temp":{"day":13.22,"min":10.57,"max":13.22,"night":10.57,"eve":12.49,"morn":13.22},"pressure":1015.76,"humidity":100,"weather":[{"id":501,"main":"Rain","description":"mäßiger Regen","icon":"10"}],"speed":7.08,"deg":269,"clouds":92,"rain":7.75}]}

My special interest lays in the params "temp":{"day":13.22,"min":10.57,"max":13.22 ... and  "description":"mäßiger Regen" but I am not able to extract this information using JSMN.

My code:

#include <JSMN.au3>

; Anfrage von Wetter mit JSON Antwort: http://api.openweathermap.org/data/2.5/forecast/daily?q=Berlin&mode=json&units=metric&cnt=1&lang=de
local $Json1 = '{"cod":"200","message":0.0268,"city":{"id":2950159,"name":"Berlin","coord":{"lon":13.41053,"lat":52.524368},"country":"DE","population":1000000},"cnt":1,"list":[{"dt":1368874800,"temp":{"day":13.22,"min":10.57,"max":13.22,"night":10.57,"eve":12.49,"morn":13.22},"pressure":1015.76,"humidity":100,"weather":[{"id":501,"main":"Rain","description":"mäßiger Regen","icon":"10"}],"speed":7.08,"deg":269,"clouds":92,"rain":7.75}]}'

Local $objJson = Jsmn_Decode($Json1)
If (Jsmn_IsObject($objJson)) Then
    ConsoleWrite('Data1:' & Jsmn_ObjGetKeys($objJson) & @CRLF)
    ConsoleWrite('Data2:' & Jsmn_ObjGet($objJson, "message") & @CRLF)
    ConsoleWrite('Data3:' & Jsmn_ObjGetCount($objJson) & @CRLF)
    ConsoleWrite('Data4:' & Jsmn_ObjExists($objJson, "message") & @CRLF)
Else
    ConsoleWrite("Kein Objekt")
EndIf

The according console output:

Data1:
Data2:0.0268
Data3:5
Data4:True

So the first level was queried successfully but if I want to query the params mentioned above I get an empty result:

AutoIt:

#include <JSMN.au3>

; Anfrage von Wetter mit JSON Antwort: http://api.openweathermap.org/data/2.5/forecast/daily?q=Berlin&mode=json&units=metric&cnt=1&lang=de
local $Json1 = '{"cod":"200","message":0.0268,"city":{"id":2950159,"name":"Berlin","coord":{"lon":13.41053,"lat":52.524368},"country":"DE","population":1000000},"cnt":1,"list":[{"dt":1368874800,"temp":{"day":13.22,"min":10.57,"max":13.22,"night":10.57,"eve":12.49,"morn":13.22},"pressure":1015.76,"humidity":100,"weather":[{"id":501,"main":"Rain","description":"mäßiger Regen","icon":"10"}],"speed":7.08,"deg":269,"clouds":92,"rain":7.75}]}'
Local $objJson = Jsmn_Decode($Json1)
If (Jsmn_IsObject($objJson)) Then
    ConsoleWrite('Data1:' & Jsmn_ObjGetKeys($objJson) & @CRLF)
    ConsoleWrite('Data2:' & Jsmn_ObjGet($objJson, "day") & @CRLF)
    ConsoleWrite('Data3:' & Jsmn_ObjGetCount($objJson) & @CRLF)
    ConsoleWrite('Data4:' & Jsmn_ObjExists($objJson, "day") & @CRLF)
Else
    ConsoleWrite("Kein Objekt")
EndIf
Local $objJson2 = Jsmn_Decode($objJson)

Console:

Data1:
Data2:
Data3:6
Data4:True

Because this is my first contact with JSON I think that I am doing something wrong with the the function "Jsmn_ObjGet". But what am I doing wrong?

Regards

mmscripting

Share this post


Link to post
Share on other sites

Try this:

#include <JSMN.au3>

; Anfrage von Wetter mit JSON Antwort: http://api.openweathermap.org/data/2.5/forecast/daily?q=Berlin&mode=json&units=metric&cnt=1&lang=de
local $Json1 = '{"cod":"200","message":0.0268,"city":{"id":2950159,"name":"Berlin","coord":{"lon":13.41053,"lat":52.524368},"country":"DE","population":1000000},"cnt":1,"list":[{"dt":1368874800,"temp":{"day":13.22,"min":10.57,"max":13.22,"night":10.57,"eve":12.49,"morn":13.22},"pressure":1015.76,"humidity":100,"weather":[{"id":501,"main":"Rain","description":"mäßiger Regen","icon":"10"}],"speed":7.08,"deg":269,"clouds":92,"rain":7.75}]}'
Local $objJson = Jsmn_Decode($Json1)

Local $List = Jsmn_ObjGet($objJson, "list") ; "list" is an array
Local $objJson2 = $List[0]
Local $Temp = Jsmn_ObjGet($objJson2, "temp") ; "temp" is an object

ConsoleWrite(Jsmn_ObjGet($Temp, "day") & @LF)
ConsoleWrite(Jsmn_ObjGet($Temp, "min") & @LF)

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

 

Share this post


Link to post
Share on other sites

Hi Ward,

ahh ok now I understand: You have do know about the JSON structure and like an encapsulation take each part in an own list / array and at some point there is only a string left which can be queried for or values.

Before I thought that I can just query the whole JSON object and the function will give me the value in return. Is this also in other programming languages a common behaviour to "encapsulate" the whole JSON object or maybe is there a way to query the whole object for the needed string?

Anyway: Thanks for your very fast and efficient help :thumbsup: !

Regards

mmscripting

Share this post


Link to post
Share on other sites

Funny that I need such a UDF now. This has to be the best JSON UDF I've seen floating around the Forums. Thanks ward.


UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Share this post


Link to post
Share on other sites

I wrote a helper function to get specific element in nested array/object returned from Jsmn_Decode() more easily.

Here is the code and example:

#Include "JSMN.au3"

Local $Json = '{"key1" : "value1", "key2" : [true, ["a", "b"], {"key3", "obj_in_array"}]}'
Local $Obj = Jsmn_Decode($Json)
Jsmn_Get_ShowResult($Obj, '["key1"]')
Jsmn_Get_ShowResult($Obj, '["key2"][0]')
Jsmn_Get_ShowResult($Obj, '["key2"][1][0]')
Jsmn_Get_ShowResult($Obj, '["key2"][2]["key3"]')

Local $Json = '{"strange key []" : "uses \\uXXXX for unsupported char in the key", "key_nospace_1" : {"key_nospace_2" : "don''t need \" if the key has no space"} }'
Local $Obj = Jsmn_Decode($Json)
Jsmn_Get_ShowResult($Obj, '["strange key [\u005D"]')
Jsmn_Get_ShowResult($Obj, '[key_nospace_1][key_nospace_2]')

Jsmn_Get_ShowResult($Obj, '[error1]')
Jsmn_Get_ShowResult($Obj, '[error2')


Func Jsmn_Get_ShowResult($Var, $Key)
    Local $Ret = Jsmn_Get($Var, $Key)
    If @Error Then
        Switch @error
            Case 1
                ConsoleWrite("Error 1: key not exists" & @LF)
            Case 2
                ConsoleWrite("Error 2: syntax error" & @LF)
        EndSwitch

    Else
        ConsoleWrite($Key & " => " & VarGetType($Ret) & ": " & $Ret & @LF)
    EndIf
EndFunc

Func Jsmn_Get($Var, $Key)
    If Not $Key Then Return $Var

    Local $Match = StringRegExp($Key, "(^\[([^\]]+)\])", 3)
    If IsArray($Match) Then
        Local $Index = Jsmn_Decode($Match[1])
        $Key = StringTrimLeft($Key, StringLen($Match[0]))

        If IsString($Index) And Jsmn_IsObject($Var) And Jsmn_ObjExists($Var, $Index) Then
            Local $Ret = Jsmn_Get(Jsmn_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 = Jsmn_Get($Var[$Index], $Key)
            Return SetError(@Error, 0, $Ret)

        Else
            Return SetError(1, 0, "")

        EndIf
    EndIf

    Return SetError(2, 0, "")
EndFunc

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

 

Share this post


Link to post
Share on other sites

I'm trying to parse the data below,

{"events":[{"world_id":2012,"map_id":873,"event_id":"659149D4-43EC-4DCB-A6BB-0B2D402B537B","state":"Warmup"},
{"world_id":2012,"map_id":873,"event_id":"72F93CD8-94AC-4234-8D86-996CCAC76A46","state":"Warmup"},
{"world_id":2012,"map_id":873,"event_id":"81F89AC2-4764-49CB-A4F1-8B7546201DC7","state":"Active"},
{"world_id":2012,"map_id":873,"event_id":"FF71DE90-423B-4685-A343-83487A330C7A","state":"Active"}]}

The end result would be an array with 3 columns for map_id, event_id, and state filled with the relevant data.

By striping '{"events":[' and ']}' from either end i managed to get the values of the first line/object but how do extract further items? I can't work out how to loop into the next line(s).

Thanks for any help. My code isn't really worth showing hence no code example.

 

Share this post


Link to post
Share on other sites

Using Jsmn_Get(), it's easy.

I will put this function into the UDF later.

#Include "JSMN.au3"

Local $Json = '{"events":[{"world_id":2012,"map_id":873,"event_id":"659149D4-43EC-4DCB-A6BB-0B2D402B537B","state":"Warmup"},{"world_id":2012,"map_id":873,"event_id":"72F93CD8-94AC-4234-8D86-996CCAC76A46","state":"Warmup"},{"world_id":2012,"map_id":873,"event_id":"81F89AC2-4764-49CB-A4F1-8B7546201DC7","state":"Active"},{"world_id":2012,"map_id":873,"event_id":"FF71DE90-423B-4685-A343-83487A330C7A","state":"Active"}]}'
Local $Obj = Jsmn_Decode($Json)

ConsoleWrite(Jsmn_Get($Obj, '["events"][0]["world_id"]') & @LF)
ConsoleWrite(Jsmn_Get($Obj, '["events"][0]["map_id"]') & @LF)
ConsoleWrite(Jsmn_Get($Obj, '["events"][0]["event_id"]') & @LF)
ConsoleWrite(Jsmn_Get($Obj, '["events"][0]["state"]') & @LF)

ConsoleWrite(Jsmn_Get($Obj, '["events"][1]["world_id"]') & @LF)
ConsoleWrite(Jsmn_Get($Obj, '["events"][1]["map_id"]') & @LF)
ConsoleWrite(Jsmn_Get($Obj, '["events"][1]["event_id"]') & @LF)
ConsoleWrite(Jsmn_Get($Obj, '["events"][1]["state"]') & @LF)

ConsoleWrite(Jsmn_Get($Obj, '["events"][2]["world_id"]') & @LF)
ConsoleWrite(Jsmn_Get($Obj, '["events"][2]["map_id"]') & @LF)
ConsoleWrite(Jsmn_Get($Obj, '["events"][2]["event_id"]') & @LF)
ConsoleWrite(Jsmn_Get($Obj, '["events"][2]["state"]') & @LF)

Func Jsmn_Get($Var, $Key)
    If Not $Key Then Return $Var

    Local $Match = StringRegExp($Key, "(^\[([^\]]+)\])", 3)
    If IsArray($Match) Then
        Local $Index = Jsmn_Decode($Match[1])
        $Key = StringTrimLeft($Key, StringLen($Match[0]))

        If IsString($Index) And Jsmn_IsObject($Var) And Jsmn_ObjExists($Var, $Index) Then
            Local $Ret = Jsmn_Get(Jsmn_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 = Jsmn_Get($Var[$Index], $Key)
            Return SetError(@Error, 0, $Ret)

        Else
            Return SetError(1, 0, "")

        EndIf
    EndIf

    Return SetError(2, 0, "")
EndFunc

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

 

Share this post


Link to post
Share on other sites

Thanks! Wow, it's easy to do once you know the correct syntax. Thanks again for the UDF and your code above really helps me understand it more now :)

Edited by Fly By Night

Share this post


Link to post
Share on other sites

Perfect, right at the time i thought of buying the $400 n/Software json Activex the native and free udf comes around, thank you very much.


$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])))''Chr("a")&"HI"Next;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)

Share this post


Link to post
Share on other sites

I'm searching through a long (>800) list looking for a specific value using the following code and my routine seems to be very slow compared to using a similar version just using _StringBetween on the raw JSON string.

I'm not sure if i can reduce the number of Jsmn_Get calls using the logic below. Is the While..Wend method below one to use or am i missing a better way to hunt for a value. Thanks again.

Func getEventstate($eventID)


; Search for a specific EventID and return it's state


Local $evState = "", $evFound = 0
Local $i = 0

    While ((Jsmn_Get($EventsObj, '["events"][' & $i & ']["event_id"]') <> "") And $evFound = 0)

        If Jsmn_Get($EventsObj, '["events"][' & $i & ']["event_id"]') == $eventID Then
            $evState = Jsmn_Get($EventsObj, '["events"][' & $i & ']["state"]')
            $evFound = 1
        EndIf

        $i = $i + 1
    WEnd

    Return ($evState)
EndFunc   ;==>getEventstate2

For reference, same using _StringBetween

Func getEventstate($eventID)

    $srcStr = '"event_id":"' & $eventID & '","state":"'
    $evState = _StringBetween($EventsJson, $srcStr, '"}')

    If $evState <> "" Then
        Return ($evState[0])
    EndIf
EndFunc   ;==>getEventstate

Share this post


Link to post
Share on other sites

You can optimize this code (and maybe any code) to avoid do the same thing everytime in the loop. For example, you can get '["events"]' object and reuse it in the loop. And then you can aslo try to modify the code to get "[' & $i & ']" only once when the $i was changed.

However, even you wrote the optimized code, I don't think it will run faster than _StringBetween. So don't try to compare with that. 


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

 

Share this post


Link to post
Share on other sites

If I wanted to load in the Events object and search through all the values of a key for a specific one, what method would you recommend? I wasn't sure how to do this optimally that is why i ended up just doing a While..Wend using the $i to increment onto the next key until i find the value i'm after. Also i wasn't sure if   '["events"][' & $i & ']["event_id"]') <> "" was the correct method to check for end of keys. I realise what i'm after is a Jsmn_Search function that looks for a value and returns how to obtain it via Jsmn_Get.

I did a test of copying key values into an array using Jsmn_Get then _StringBetween and Jsmn_Get was a lot faster on a test of about 1600 keys.

Edited by Fly By Night

Share this post


Link to post
Share on other sites

Here is the JSMN_Get function that Ward wrote in post #12 written to allow both delimiter notation (dot, comma, pipe, whatever notation) and JSON notation.

; #FUNCTION# ===================================================================
; Name:             Jsmn_Get
; Description:    Retrieves a value from the scripting.dictionary key specified
;
; Parameter(s):
;                       $Object     Scripting dictionary object
;
;                       $Key        Key for the value you want to retrieve. Follows delimiter based or JSON based format depending on the notation parameter
;
;                       $Notation
;                                       0 - Delimiter based - Key1.Key2
;                                       1 - JSON format based ["key1"]["key2"]
;
;                       $Delim      If notation = 0 Then this is the delimiter between keys
;
; Requirement(s):   JSMN JSON library by Ward.
;
; Return Value(s):
;                           On Success  Returns value from key
;
;                           On Failure      Returns a blank string and an error value.
;                                               @error
;                                                   1 - key does not exist
;                                                   2 - notation syntax error
;                                               @Extended - Only used if notation = 0
;                                                   See StringSplit error codes
;
; Author(s):    Ward (modified slightly by SantaRyan to add delimiter notation)
;===============================================================================
Func Jsmn_Get($Object, $Key, $Notation = 0, $Delim = ".")
    If Not $Key Then Return $Object
    If IsKeyword($Notation) Then $Notation = 0
    Local $Index, $Match, $Ret
    If $Notation = 0 Then
        $Match = StringSplit($Key, $Delim, 1)
        If IsArray($Match) Then
            $Index = $Match[1]
            $Key = ""
            For $i = 2 To $Match[0]
                $Key &= $Match[$i] & $Delim
            Next
            $Key = StringTrimRight($Key, 1)
        Else
            Return SetError(2, 0, "")
        EndIf
    ElseIf $Notation = 1 Then
        $Match = StringRegExp($Key, "(^\[([^\]]+)\])", 3)
        If IsArray($Match) Then
            $Index = Jsmn_Decode($Match[1])
            $Key = StringTrimLeft($Key, StringLen($Match[0]))
        Else
            Return SetError(2, 0, "")
        EndIf
    EndIf
    If IsString($Index) And Jsmn_IsObject($Object) And Jsmn_ObjExists($Object, $Index) Then
        $Ret = Jsmn_Get(Jsmn_ObjGet($Object, $Index), $Key, $Delim)
        Return SetError(@error, 0, $Ret)
    ElseIf IsNumber($Index) And IsArray($Object) And $Index >= 0 And $Index < UBound($Object) Then
        $Ret = Jsmn_Get($Object[$Index], $Key, $Delim)
        Return SetError(@error, 0, $Ret)
    Else
        Return SetError(1, 0, "")
    EndIf
EndFunc   ;==>Jsmn_Get
Edited by santaryan

Share this post


Link to post
Share on other sites

Hello,

thanks for this UDF, it has been really helpful so far. However, I got one JSON string that seems impossible to decode with this UDF (I validated it with a JSON validator, so does not seem to be invalid):

I doesn't work in this form:

#Include <JSMN.au3>

$JSON='{"a":{"742597609":{"v":673,"p":4.91,"lb":"test1","av":58,"sl":11.6},"534165346":{"v":777,"p":5.66,"lb":"test2","av":58,"sl":13.3}},"b":16092018}'

Local $objJson = Jsmn_Decode($JSON)

If Jsmn_IsObject($objJson) Then
    Local $auctions = Jsmn_ObjGet($objJson, "a")
    For $i = 0 To UBound($auctions)-1
        Local $objJson2 = $auctions[$i]
        ConsoleWrite(Jsmn_ObjGet($objJson2, "p"))
    Next
EndIf

When I transform the JSON string like this, it produces an output:

#Include <JSMN.au3>

$JSON='{"a":{"742597609":{"v":673,"p":4.91,"lb":"test1","av":58,"sl":11.6},"534165346":{"v":777,"p":5.66,"lb":"test2","av":58,"sl":13.3}},"b":16092018}'

;JSMN compatibility
$JSON=StringRegExpReplace($JSON,'"\d{9}":','')
$JSON=StringReplace($JSON,'{"a":{','{"a":[')
$JSON=StringReplace($JSON,'}},','}],')

;produces
;$JSON='{"a":[{"v":673,"p":4.91,"lb":"test1","av":58,"sl":11.6},{"v":777,"p":5.66,"lb":"test2","av":58,"sl":13.3}],"b":16092018}'

Local $objJson = Jsmn_Decode($JSON)

If Jsmn_IsObject($objJson) Then
    Local $auctions = Jsmn_ObjGet($objJson, "a")
    For $i = 0 To UBound($auctions)-1
        Local $objJson2 = $auctions[$i]
        ConsoleWrite(Jsmn_ObjGet($objJson2, "p"))
    Next
EndIf

What am I doing wrong ? Is it possible to get the auction details (like "p" in this example) without transforming the JSON string ?

Edited by level20peon

Share this post


Link to post
Share on other sites

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

  • Similar Content

    • By Miliardsto
      You can see my script to POST json and the problem where occurs backslashes before quotations. Second problem is the apperance , there is no new lines for every new value.
      LOOK in attached images!
       
      You can see rest api on the screen and with id = 0 its made my postman and the rest by autoit (with backslashes)
       
      Func jsonSave() ; Make login request to server JSON POST Local $data, $request Local $obj Local $adress = 'http://35.195.249.40:3004/msg' Json_Put($Obj, ".msgName", "Point HPs") Json_Put($Obj, ".msg", "Not pointed correctly") Json_Put($Obj, ".username", "karolek890") Local $Json = Json_Encode($Obj,$JSON_UNESCAPED_SLASHES) ; WITHOUT preetier becouse it makes clashes r n and t only works in autoit $request = _httpRequestBot($adress, 'POST', $Json) ; only get login if correct then success If @error Then Exit MsgBox(0, "Error", "Open method returned @error = " & @error & " and @extended = " & @extended) Else ConsoleWrite("Data to json server posted!") EndIf EndFunc  
      Im using this JSON UDF
       
       
       


    • By jchd
      Here's a new version of my Dump.au3 file (dirty). I've recently added support to dissect (dump) as a treeview-like view any string in the variable conforming to a strict JSON grammar, whereever said string is: as a standalone string variable or in an array or a map. AFAICT the only relaxed constraint not implemented here is that numbers in parsed JSON may have leading zeroes, although leading zeroes are forbidden in pure JSON specifications. If required it wouldn't be hard to add this constraint.
      @c.haslam (among others) may find it useful. Use freely.
      Dump.au3
    • By TheXman
      This UDF brings the power and flexibility of jq to AutoIt scripts.  jq is an open-source, powerful, and flexible command-line based JSON processor.  As it says on their website, jq is like 'sed' for JSON.  jq can be used for the simplest of tasks like retrieving JSON objects and values, to very advanced JSON processing using its numerous built-in functions and conditional processing.  Its built-in functions can handle math, selection, conditional processing, mapping, object and array manipulation, flattening, reduction, grouping, and much more.  You can even create your own jq functions.  You can learn more about jq and even play with it in real-time, using jq's online jq playground, all on their website.
      Here and some helpful links to get you more familiar with jq, what can be done with it, its built-in functions, and its syntax.
      jq Website: https://stedolan.github.io/jq/ jq Manual: https://stedolan.github.io/jq/manual/ jqWiki (FAQ, Cookbook, Advanced Topics) https://stedolan.github.io/jq/manual/ jq Online Testing Playground: https://jqplay.org/ jq is a single 32 or 64 bit executable that has no other dependencies.  Just like using the SQLite UDF, the only requirement to use this UDF is that the jq executable reside in a location in which the UDF can execute it.  The latest win32 & win64 versions have been included in the UDF download.  You can always get newer versions from the jq website.
      I don't consider this a replacement for some of the other JSON UDFs like the one based on JSMN.  If speed and simple JSON parsing are you primary goals, then other UDFs may be a better choice.  However, if you like having the power to do just about anything related to JSON processing/manipulation, using a single UDF, then jq may be worth checking out.  It can be used by novices and experts alike.  Below, is a brief explanation of how jq works, how to use the jq UDF, and a few examples of how to do some simple tasks.  If you want to learn more about jq and what it can do, I would highly suggest checking out the jq website and some of the other resources listed above.
      jq at a high level
      Like 'sed', jq reads JSON in, either through STDIN or one or more files, processes it thru one or more "filters", and outputs the results.  You can, optionally, supply "options" that affect how it reads the input, where it gets its "filters", and how it writes its output.  It looks a little like this:
      JSON ---> jq processor (using supplied filters and options) ---> Output
      So in jq lingo, you basically use "Filters" to tell jq what you want it to do.  So in the UDF file, that is why the main functions ( _jqExec() and _jqExecFile() ) refer to filters and options.  Please make note that jq works with relatively strict JSON.  This means that all JSON read must be conform to the standard.  Luckily, jq is pretty good at identifying where a format error exists in non standard JSON.
      The jq UDF
      There are 2 main funtions in the UDF file, _jqExec and jqExecFile.  With these 2 functions, you can pretty much do anything that jq can do.  The only difference between to two functions is whether the JSON is supplied by a string or a file.  The 2 primary functions simply call the jq executable with the supplied information, after properly formatting the parameters.  There are additional functions in the UDF to easily pretty-print your json, compact-print your json, dump the json data with its associated paths, and see if specific JSON keys exist, but they all just execute the _jqExec or _jqExecFile function with the proper filter.  There are also a couple of extra functions to display what version of the UDF and jq executable you are currently using.  There are also a couple of functions to enable and disable logging of jq information for debugging purposes.  Most of the jq UDF file functions return an @error if unsuccessful.  Some also include @extended info.  Please see the actual function headers for more information on their usage and return values.
      The 2 primary functions below just format your jq request and pass it on the jq executable.  The functions will also properly escape double quotes (") that are used in the filter.  For most simple tasks, you just need to supply the JSON source and a filter.
      _jqExec($sJson, $sFilter, $sOptions = Default, $sWorkingDir = Default) Or _jqExecFile($sJsonFile, $sFilter, $sOptions = Default, $sWorkingDir = Default) Using jq in your script
      As stated earlier, the jq executable must reside somewhere where the script can locate and execute it.  The _jqInit() function always has to be executed before any jq processing occurs.  _jqInit() merely locates the executable or uses the supplied path.  It also clears any previous debug log.  The jq UDF folder contains a jq example script that has several examples to how to do some of the most common JSON processing tasks.  Here are a few examples to get you started:

      How to pretty-print some JSON
      #include "jq.au3" _jqInit() If @error Then Exit ConsoleWrite("ERROR: Unable to initialize jq - @error = " & @error & @CRLF) $sJson = '{"fruits":[{"Apple":{"color":"Red","season":"Fall"}}, {"Banana":{"color":"Yellow","season":"Summer"}}]}' $sCmdOutput = _jqPrettyPrintJson($sJson) ConsoleWrite(@CRLF & "Pretty-Print JSON" & @CRLF & $sCmdOutput & @CRLF) How to compact-print some JSON
      #include "jq.au3" _jqInit() If @error Then Exit ConsoleWrite("ERROR: Unable to initialize jq - @error = " & @error & @CRLF) $sJson = '{ "fruits" : [{"Apple" : {"color":"Red","season":"Fall"}}, {"Banana":{"color":"Yellow","season":"Summer"}}]}' $sCmdOutput = _jqCompactPrintJson($sJson) ConsoleWrite(@CRLF & "Compact-Print JSON" & @CRLF & $sCmdOutput & @CRLF) Dump JSON data (paths and values)
      #include "jq.au3" _jqInit() If @error Then Exit ConsoleWrite("ERROR: Unable to initialize jq - @error = " & @error & @CRLF) $sJson = '{ "fruits" : [{"Apple" : {"color":"Red","season":"Fall"}}, {"Banana":{"color":"Yellow","season":"Summer"}}]}' $sCmdOutput = _jqDump($sJson) ConsoleWrite(@CRLF & "Dump JSON paths and values" & @CRLF & $sCmdOutput & @CRLF) How to GET JSON values
      #include "jq.au3" _jqInit() If @error Then Exit ConsoleWrite("ERROR: Unable to initialize jq - @error = " & @error & @CRLF) $sJson = '{"Apple" : {"color":"Red","season":"Fall"}, "Banana":{"color":"Yellow","season":"Summer"}}' $sFilter = '.Banana.color' $sCmdOutput = _jqExec($sJson, $sFilter) ConsoleWrite("Get color of banana" & @CRLF) ConsoleWrite("Input: : " & _jqCompactPrintJson($sJson) & @CRLF) ConsoleWrite("Filter : " & $sFilter & @CRLF) ConsoleWrite("Output : " & $sCmdOutput & @CRLF) or
      #include "jq.au3" _jqInit() If @error Then Exit ConsoleWrite("ERROR: Unable to initialize jq - @error = " & @error & @CRLF) $sJson = '{"Apple" : {"color":"Red","season":"Fall"}, "Banana":{"color":"Yellow","season":"Summer"}}' $sFilter = 'getpath(["Banana", "color"])' $sCmdOutput = _jqExec($sJson, $sFilter) ConsoleWrite("Get color of banana" & @CRLF) ConsoleWrite("Input: : " & _jqCompactPrintJson($sJson) & @CRLF) ConsoleWrite("Filter : " & $sFilter & @CRLF) ConsoleWrite("Output : " & $sCmdOutput & @CRLF)  
      Check for the existence of a key
      #include "jq.au3" _jqInit() If @error Then Exit ConsoleWrite("ERROR: Unable to initialize jq - @error = " & @error & @CRLF) $sJson = '{"Apple":{"color":"Red","season":"Fall"}, "Banana":{"color":"Yellow","season":"Summer"}}' $sFilter = '.Banana | has("color")' $sCmdOutput = _jqExec($sJson, $sFilter) ConsoleWrite("Check for existence of color key within Banana object" & @CRLF) ConsoleWrite("Input: : " & _jqCompactPrintJson($sJson) & @CRLF) ConsoleWrite("Filter : " & $sFilter & @CRLF) ConsoleWrite("Output : " & $sCmdOutput & @CRLF) Count of how many Items in an object
      #include "jq.au3" _jqInit() If @error Then Exit ConsoleWrite("ERROR: Unable to initialize jq - @error = " & @error & @CRLF) $sJson = '{"Apple":{"color":"Red"}, "Banana":{"color":"Yellow","season":"Summer"}}' $sFilter = '.Banana | length' $sCmdOutput = _jqExec($sJson, $sFilter) ConsoleWrite("How many items in the Banana object" & @CRLF) ConsoleWrite("Input: : " & _jqCompactPrintJson($sJson) & @CRLF) ConsoleWrite("Filter : " & $sFilter & @CRLF) ConsoleWrite("Output : " & $sCmdOutput & @CRLF) How to PUT/Create/Modify JSON
      #include "jq.au3" _jqInit() If @error Then Exit ConsoleWrite("ERROR: Unable to initialize jq - @error = " & @error & @CRLF) $sInput = "" $sFilter = 'setpath(["Apple","color"];"Red") | setpath(["Banana","color"];"Yellow") | setpath(["Banana","season"];"Summer")' $sOptions = '-n' ;required if no input supplied $sCmdOutput = _jqExec($sInput, $sFilter, $sOptions) ConsoleWrite("Update/Create JSON" & @CRLF) ConsoleWrite("Filter : " & $sFilter & @CRLF) ConsoleWrite("Output : " & @CRLF & $sCmdOutput & @CRLF) List all of the fruits (top-level keys)
      #include "jq.au3" _jqInit() If @error Then Exit ConsoleWrite("ERROR: Unable to initialize jq - @error = " & @error & @CRLF) $sJson = '{"Apple":{"color":"Red"}, "Banana":{"color":"Yellow","season":"Summer"}}' $sFilter = 'keys | .[]' $sCmdOutput = _jqExec($sJson, $sFilter) ConsoleWrite("List all top-level keys (fruits)" & @CRLF) ConsoleWrite("Input : " & $sJson & @CRLF) ConsoleWrite("Filter : " & $sFilter & @CRLF) ConsoleWrite("Output : " & @CRLF & $sCmdOutput & @CRLF) The examples above, and the ones in the example file, merely scratch the surface of what jq can do.  It may look intimidating at first but it really isn't that bad once you start playing with it.
      If you have any suggestions on how to make the UDF better, or find a bug, please let me know.  I only started using it about a week ago.  Nevertheless, if you have any questions regarding the UDF, or how to perform a certain task using jq, I'll try my best to answer them.  Since jq has been around for a while now, there's also several jq-related questions and answers on StackOverflow.
      If you work with JSON, I hope you find this UDF useful.
       
      Download:
      jq_udf_v1.1.1.zip
    • By Skysnake
      I know how JSON works. However JSON data is typically received from web based servers. 
       
      My question is:
      Has anyone considered to use, or currently actively using JSON as an internal data container? 
      Internal here as in an ordinary AutoIt data type, generated, populated and manipulated within an AutoIt script, without any external data sources. 
      The JSON and BinaryCall UDFs work well and appear the de facto defaults. Are there any thoughts on using JSON for internal variable values instead of the typical array? 
      Also, there can be situations where such a JSON collection contains an array and it will have to be parsed using typical array functions. 
      Currently I am working on a small project where I have to keep and use various identifiers from different sources. There are several ideas in this regard, some involving SQL child tables and arrays stored with keys (maps), which lead me to think that JSON may be a more suitable data container. It readily shrinks and stretches, allowing for dynamic data growth.  JSONs ability to add new repeating data groups on the fly makes it particularly powerful and appealing. 
      Ideas and suggestions welcome
      Skysnake
    • By jantograaf
      Hi all,
      I'm trying to create a script that runs a JSON-query and then can retrieve some variables out of the returned, decoded object using JSON.au3. I have tried some other examples on this forum, but I'm stuck at one point. My query works perfectly and gets loaded into the variable $data. Then, decoding $data to $object seems to work as well. But then I can't get the date-field out of this JSON-structure with my script.
      The JSON-structure returned looks like this:
      { "content": [ { "id": "451ec583-8f27-4926-82a3-a2d85e57a110", "createdDate": "2018-08-08T08:40:57.449004Z", "updatedDate": "2018-08-08T08:40:57.449004Z", "lastOpenedDate": "2018-08-08T08:40:57.449004Z", "date": "2018-04-26T00:00:00", "description": "X-Ray Exam", "patient": { "id": "f857238a-c75d-4760-b8d1-8f50f8f9bbfa", "createdDate": "2018-08-08T08:40:37.623976Z", "updatedDate": "2018-08-08T08:40:37.623976Z", "lastOpenedDate": "2018-08-08T08:40:37.623976Z", "name": "Fuerstonia", "birthDate": "2014-06-08", "breed": "", "chip": "", "color": "", "damsire": "", "sire": "", "neutered": false, "orthancUuid": "", "sex": "U", "species": "Paard", "ueln": "De 431310762114", "pmsReference": "", "origin": "" }, "type": "study", "accessionNumber": "KME201806960467", "instanceUid": null, "orthancUuid": "", "sent": false, "seriesCount": 0, "modalityType": "RX", "typeAndModality": "study RX", "client": { "id": "be627195-8458-4927-8446-f1ef37b917a4", "createdDate": "2018-08-08T08:40:31.433968Z", "updatedDate": "2018-08-08T08:40:31.433968Z", "lastOpenedDate": "2018-08-08T09:26:49.512298Z", "via": "", "extraInfo": "", "pmsReference": "", "contact": { "id": "406cc555-c491-4c29-b6bb-8d903f0e35a9", "createdDate": "2018-08-08T08:40:31.428968Z", "updatedDate": "2018-08-08T08:40:31.428968Z", "lastName": "Client 1", "firstName": "", "company": "", "email": "", "language": "nl", "phone": "", "address": { "id": "6fc7703c-137a-4e0a-ba96-8c7f38f2044b", "city": "", "country": "", "line": "", "postalCode": "" } } } }, My script looks like this:
      #RequireAdmin #include <json.au3> #include <inet.au3> #include <File.au3> ;Create a handle to a logfile (will be created if it doesnt exist) Global $logfile = FileOpen("C:\VSOL\VSTK\Logs\MigrationFix\MigrationFix.log",9) FileWriteLine($logfile,"Start script") ;Create the URL with the JSON-query $URL = "http://localhost:8080/v0/studies/?seriesCount=1" ;Catch the query output into a variable $data = _INetGetSource($URL) ;Check if there is any data at all in this variable, if not, exit If Not $data Then MsgBox(1,"Error","No answer. Server is probably not running.") Exit EndIf ;For debugging purposes FileWriteLine($logfile,$data) ;Decode the JSON_string into a useable object $object = Json_Decode($data,1000) If @error Then FileWriteLine($logfile,"Error decoding JSON") Exit EndIf Local $i = 0 ;Start a loop to retrieve the study date of each study... While 1 $study_date = json_get($object,'[' & $i & '].date') If @error Then FileWriteLine($logfile,"Study-Date retrieval error") ExitLoop EndIf $i = $i + 1 WEnd ;Close the logfile FileWriteLine($logfile,"Stop script") FileClose($logfile) ;Open the logfile for quick reference ShellExecute("C:\VSOL\VSTK\Logs\MigrationFix\MigrationFix.log") If believe it has something to do with my json_get($object...)-command. Anyone who can point me in the right direction?
      Thanks in advance!
      Kind regards
×
×
  • Create New...