Jump to content
Ward

A Non-Strict JSON UDF (JSMN)

Recommended Posts

Ward

The $auction you get from Jsmn_ObjGet($objJson, "a") is an object, not an array.

Your code should be modified like this:

#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")
    Local $Keys = Jsmn_ObjGetKeys($auctions)
    For $i = 0 To UBound($Keys) - 1
        Local $objJson2 = Jsmn_ObjGet($auctions, $Keys[$i])
        ConsoleWrite(Jsmn_ObjGet($objJson2, "p") & @LF)
    Next
EndIf
  • Like 1

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

 

Share this post


Link to post
Share on other sites
level20peon

I sometimes get this error:

JSMN.au3 (403) : ==> Error in expression.:
Return $Object.Item(String($Key))
Return ^ ERROR

I am trying to filter what is being decoded as JSON in the first place using StringRegExp on the input as well as using the Jsmn_IsObject function, but that sometimes doesn't seem to do the trick.

Does anyone know what could cause this error as well as what other error catching mechanism I could use to prevent it from happening ?

Share this post


Link to post
Share on other sites
Siahtech

 

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

Old thread I just needed to say Thanks

I spent Days trying to decode and use my Json file. I found and used your Code and it worked =)

Thanks a TON!!!!

The json part in my script

#Include "JSMN.au3"
#Include "File.au3"
local $Json1_2
_FileReadToArray(@ScriptDir & "\DatabaseS.db",$Json1_2,0)
$json1_3 = _ArrayToString($Json1_2,"")
$Json2 = StringStripWS($Json1_3, 8)
Local $Obj1 = Jsmn_Decode($Json2)
$resault = Jsmn_Get($Obj1, '["response"]["prices"]["10"]["6"]["0"]["last_update"]')
ConsoleWrite($resault & @CRLF)

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
Edited by Siahtech

Share this post


Link to post
Share on other sites
this-is-me

I am completely unable to understand how to access arrays using the latest JSMN.au3 downloaded from the first post, Jsmn_Get from >post #12 and dot notation. In fact, that Jsmn_Get doesn't seem to be working with old-style notation either. Can someone redo or recommend a way to access json information with dot notation that actually works?

 

#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") & @CRLF) ;Doesn't work
ConsoleWrite(Jsmn_Get($Obj, '["events"][0]["world_id"]', 1) & @LF) ;Doesn't work

; #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 this-is-me

Who else would I be?

Share this post


Link to post
Share on other sites
this-is-me

24-hr bump. I really want to use dot notation to access JSON objects using JSMN. If someone can "fix" the existing code, or rewrite it I would appreciate it. I don't begin to understand what to do with it.

EDIT: After much trouble, I realise two problems with Jsmn_Get. First, the $Index was not being typecast as a number in the case of a dot notation. Therefore, I added a simple typecast.
 

$Index = $Match[1]
;Add the following
$Index = (StringIsInt($Index)=1?Number($Index):$Index)

Secondly, when the function was called by itself, it was called with improper parameters (missing the notation flag):
 

;OLD: $Ret = Jsmn_Get(Jsmn_ObjGet($Object, $Index), $Key, $Delim)
$Ret = Jsmn_Get(Jsmn_ObjGet($Object, $Index), $Key, $Notation, $Delim)

;OLD: $Ret = Jsmn_Get($Object[$Index], $Key, $Delim)
$Ret = Jsmn_Get($Object[$Index], $Key, $Notation, $Delim)

With these problems solved, everything works swimmingly.

Edited by this-is-me

Who else would I be?

Share this post


Link to post
Share on other sites
TechCoder

Great UDF, been using it to work with JSON much easier than other functions.  I'm also using Jsmn_Get (which is a massive time saver).

However, getting this one string to decode properly has me stumped.

The Decode function shows no error (which there isn't that I can find separating it manually - see the commented section), though $JSMN_PRETTY_PRINT does not break the "groups" out properly (at least, that is what it seems to me).

What am I missing?

#Include "JSMN.au3"

Test3()

Func Test3()

Local $string2test = '{"id":"6","username":"USERNAME","firstName":"FirstName","lastName":"LastName","emailAddress":"example@example.com","phoneNumber":"","lastLogin":"","statusId":"1","timezone":"America\/Chicago","organization":"","position":"","language":"en_us","icsUrl":null,"customAttributes":[{"id":"5","label":"user attribute","value":null,"links":[{"href":"http:\/\/example.com\/Attributes\/5","title":"get_custom_attribute"}],"message":null}],"permissions":[{"id":"1","name":"","links":[{"href":"http:\/\/example.com\/Resources\/1","title":"get_resource"}],"message":null},{"id":"2","name":"","links":[{"href":"http:\/\/example.com\/Resources\/2","title":"get_resource"}],"message":null}],"groups":[{"links":[{"href":"http:\/\/example.com\/Groups\/1","title":"get_group"}],"message":null,"id":"1","name":"Administrators"},{"links":[{"href":"http:\/\/example.com\/Groups\/5","title":"get_group"}],"message":null,"id":"5","name":"Students"}],"links":[],"message":null}'

    Local $Json1    = $string2test
    Local $Data1 = Jsmn_Decode($Json1)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Data1 = ' & $Data1 & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

    Local $Json2 = Jsmn_Encode($Data1, $JSMN_UNQUOTED_STRING)
    Local $Data2 = Jsmn_Decode($Json2)

    Local $Json3 = Jsmn_Encode($Data2, $JSMN_PRETTY_PRINT, "  ", "\n", "\n", "")
    Local $Data3 = Jsmn_Decode($Json3)

    Local $Json4 = Jsmn_Encode($Data1, $JSMN_STRICT_PRINT)

    ConsoleWrite("Test3 Unquoted Result: " & $Json2 & @CRLF)
    ConsoleWrite("Test3 Pretty Result: " & $Json3 & @CRLF)
    Return (StringLen($Json3) >= StringLen($Json1))
EndFunc

#cs
    Here is how the string breaks down (manually)
    NOTE HOW GROUPS COMES OUT CORRECTLY
{
    "id":"6",
    "username":"USERNAME",
    "firstName":"FirstName",
    "lastName":"LastName",
    "emailAddress":"example@example.com",
    "phoneNumber":"",
    "lastLogin":"",
    "statusId":"1",
    "timezone":"America\/Chicago",
    "organization":"",
    "position":"",
    "language":"en_us",
    "icsUrl":null,
    "customAttributes": [
        {
            "id":"5",
            "label":"user attribute",
            "value":null,
            "links":[
                {
                    "href":"http:\/\/example.com\/Attributes\/5",
                    "title":"get_custom_attribute"
                }
            ],
            "message":null
        }
    ],
    "permissions":[
        {
            "id":"1",
            "name":"",
            "links":[
                {
                    "href":"http:\/\/example.com\/Resources\/1",
                    "title":"get_resource"
                }
            ],
            "message":null
        },
        {
            "id":"2",
            "name":"",
            "links":[
                {
                    "href":"http:\/\/example.com\/Resources\/2",
                    "title":"get_resource"
                }
            ],
            "message":null
        }
    ],
    "groups":[             <<<<======= HERE, IT IS CORRECT - THOUGH CHECK YOUR CONSOLE OUTPUT!
        {
            "links":[
                {
                    "href":"http:\/\/example.com\/Groups\/1",
                    "title":"get_group"
                }
            ],
            "message":null,
            "id":"1",
            "name":"Administrators"
        },
        {
            "links":[
                {
                    "href":"http:\/\/example.com\/Groups\/5",
                    "title":"get_group"
                }
            ],
            "message":null,
            "id":"5",
            "name":"Students"
        }
    ],
    "links":[],
    "message":null
}
#ce

Share this post


Link to post
Share on other sites
TechCoder

found it!

"name":""

the UDF doesn't like the empty string - it wants ==>null<== or some with-character(s) string.

So, the 'fix' - I did a quick StringReplace......

$string2test = StringReplace($string2test,'""','null')

puts everything back in place.

Share this post


Link to post
Share on other sites
lxxl

Guys, i can't get this magic ...

here is my JSON array

[

  {

    "Sysinfo": [

      {

        "Name": "System",

        "Description": "System",

        "Type": "System",

        "Capabilities": "System",

        "Manufacturer": "",

        "Properties": [

          {

            "Name": "User Application Total Space",

            "Description": "The total space for user applications on the device.",

            "Type": "DISCRETEMEASUREMENT",

            "Value": "5.42 GB"

          },

          {

            "Name": "User Application Percentage Free Space",

            "Description": "The percentage of free space for user applications on the device.",

            "Type": "PERCENT",

            "Value": "0.949643"

          },

          {

            "Name": "Android Build Id",

            "Description": "The version of Android running on the system",

            "Type": "STRING",

            "Value": "JDQ39"

          }

        ]

      }

    ]

  },

  {

    "Scripts": [

      {

        "Script": "123a",

        "Date": "Mar 24, 2014 12:52:31 PM",

        "Result": "Failed",

        "Tests": [

          {

            "Name": "APT",

            "Device": "System Memory",

            "Result": "Pass"

          }

        ]

      }

    ]

  }

]

i try to adapt this:

local $Json1_2
_FileReadToArray("TestHistory.txt",$Json1_2)
$json1_3 = _ArrayToString($Json1_2,"")
$Json2 = StringStripWS($Json1_3, 8)
Local $Obj1 = Jsmn_Decode($Json2)
$resault = Jsmn_Get($Obj1, '[0]["Sysinfo"]["0"]["7"]["User Application Total Space"]')
ConsoleWrite($resault & @CRLF)

but all time i cant get resoults, maybe its to complicated for me :D

any help ?

thxx

Edited by lxxl

Share this post


Link to post
Share on other sites
TechCoder

Not sure what you are trying to get from the string (as your code shows you asking for the result name, not the variable...)

you will see that, at the end (if not before) you are asking for the "User Application Tool Space", which is the RESULT - you should be asking for, perhaps 'Name' there - so the result can come back - example on that below

Here is a tip on how I got used to using the UDF and JSON in general.

Take it a step at a time!

instead of 

$resault = Jsmn_Get($Obj1, '[0]["Sysinfo"]["0"]["7"]["User Application Total Space"]')

just go to

$resault = Jsmn_Get($Obj1, '[0]')

and see what you get (should be something you recognize)

then, the next bit (once you select what you really want)

$resault = Jsmn_Get($Obj1, '[0]["Sysinfo"]')

etc.

Like the old saying - you CAN eat an elephant, just take it in small bites - and keep at it until you are done.

 

the way I look at it is, for a START,

1. replace [{ with a [0]

(start with 0 and go from there until you get what you want...)

2. if you find the variable you want in the list, add that to your 'get' string

3. go back to step 1 when needed

Now, to get the result of "User Application Tool Space" as I believe you are looking for in your example, you need to look at;

[0]['Sysinfo'][[0]['Properties'][0]['Name']

More simple now?

Share this post


Link to post
Share on other sites
lxxl

Many thx for fast reply TechCoder, good explanation and way to eat it, after add

$resault = Jsmn_Get($Obj1, '[0]')
i in console popup only @CRLF) so maybe the _filetoarray fail dunno

Share this post


Link to post
Share on other sites
TechCoder

Yeah, I now see what it is...... - you are trying too hard!

Not sure what all that Array stuff is - you don't need it when working with JSON - it, by definition, is an array-decrypter (of sorts) - whatever you call it, JSON is a method in/of itself and you are trying to tear it apart yourself, then looking for the tools to do the work.

Don't try so hard!  ;)

Basically, all you need when using this UDF: 

1. take the incoming JSON code (in your case, coming from a .txt file - it might come from a result or anywhere... - but LEAVE IT ALONE AS JSON)

2. JSMN_DECODE it to an object.  

3. use JSMN_GET.  

That's it!

This works (using the demo from JSMN and your data to show you the full results) - notice you only need ONE include, which is this UDF!

#include "JSMN.au3"


local $Json1
$Json1 = FileRead("TestHistory.txt")
Local $Data1 = Jsmn_Decode($Json1)

; ************************************************************************************
; these lines are NOT NEEDED in your live system, just here to show the output
Local $Json2 = Jsmn_Encode($Data1, $JSMN_UNQUOTED_STRING)
Local $Data2 = Jsmn_Decode($Json2)
Local $Json3 = Jsmn_Encode($Data2, $JSMN_PRETTY_PRINT, "  ", "\n", "\n", "")
ConsoleWrite("Test3 Unquoted Result: " & $Json2 & @CRLF)
ConsoleWrite("Test3 Pretty Result: " & $Json3 & @CRLF)
; the above lines are not needed in a live system
; ************************************************************************************

$resault = Jsmn_Get($Data1, '[0]["Sysinfo"][0]["Properties"][0]["Name"]')
ConsoleWrite($resault & @CRLF)

and, for future reference, when you post code - go ahead and put in the #includes you are using (makes it simpler for someone testing your code, as well as know what you are using - it might be that you have the wrong includes sometimes....)

So, end result - let the tool do the work.  

(BTW, my 'tip' on going step at a time didn't work on this - because it starts off with an array - the data I have been working with is a bit different and that stepping through worked for me - guess it all depends on the data  :   However, the 'replace [{ with [0] works on your data as well as mine, so that seems a good 'rule'... :sweating: )

Share this post


Link to post
Share on other sites
lxxl

hey TechCoder, thxx for code now all looks better with

ConsoleWrite("Test3 Unquoted Result: " & $Json2 & @CRLF)

i can get this in console

>"C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "C:\Users\x\Desktop\code\log.au3" /UserParams    
+>07:42:25 Starting AutoIt3Wrapper v.2.1.0.8    Environment(Language:0409  Keyboard:00000415  OS:WIN_7/Service Pack 1  CPU:X64 OS:X64)
>Running AU3Check (1.54.22.0)  from:C:\Program Files (x86)\AutoIt3
+>07:42:25 AU3Check ended.rc:0
>Running:(3.3.8.1):C:\Program Files (x86)\AutoIt3\autoit3.exe "C:\Users\x\Desktop\code\log.au3"    
Test3 Unquoted Result: [{Sysinfo:[{Name:System,Description:System,Type:System,Capabilities:System,Manufacturer:,Properties:[{Name:"User Application Total Space",Description:"The total space for user applications on the device.",Type:DISCRETEMEASUREMENT,Value:"5.42 GB"},{Name:"User Application Percentage Free Space",Description:"The percentage of free space for user applications on the device.",Type:PERCENT,Value:"0.949643"},{Name:"Android Build Id",Description:"The version of Android running on the system",Type:STRING,Value:JDQ39}]}]},{Scripts:[{Script:"123a",Date:"Mar 24, 2014 12:52:31 PM",Result:Failed,Tests:[{Name:APT,Device:"System Memory",Result:Pass}]}]}]

+>07:42:25 AutoIT3.exe ended.rc:0
>Exit code: 0    Time: 1.650

 

so code is working !, move over

Local $Json3 = Jsmn_Encode($Data2, $JSMN_PRETTY_PRINT, "  ", "\n", "\n", "")

print 1:1 txt file and this is good as well

but this damm code give me only @CR

$resault = Jsmn_Get($Data1, '[0]["Sysinfo"][0]["Properties"][0]["Name"]')
ConsoleWrite($resault & @CRLF)

with Func Jsmn_Get do you have this one:

; #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

?

Share this post


Link to post
Share on other sites
TechCoder

I'm really not understanding your post - again, please put in the full code because your message is mixed - "works!" and "not" in one - not sure if you took out something or what from the code I gave you, which works fine and as expected on my system.

And, yes, you do have to add in the jsmn_get function to the UDF (I did that in my copy the first day - forgot about that.... - the one that coded it said he would add it but it is not in the first post download - yes, you have to have it as well - either in the UDF or in the program you are using....) - though if you are not getting errors on that, it seems you have that function (pulled from another post is what I use.)

Is that the problem you are discussing?  Again, just not clear (I'm in the middle of a big project and can only glance at the replies - if they aren't 'easy' to figure out, I have to move on {i.e., helping others with their coding issue is not my primary job - but I do what I can...})   When asking for help, I try to follow a tip an old-timer told me years ago "Before you post, check to make sure a 3rd grader can understand it" - then, there is no guessing for the person trying to help you.

Share this post


Link to post
Share on other sites
tes5884

I am trying to use this UDF and keep getting stuck. This is the code I have:

$json1 = '{"coord":{"lon":-0.13,"lat":51.51},"sys":{"type":1,"id":5091,"message":0.2133,"country":"GB","sunrise":1406607636,"sunset":1406663600},"weather":[{"id":800,"main":"Clear","description":"Sky is Clear","icon":"01n"}],"base":"cmc stations","main":{"temp":295.47,"pressure":1014,"humidity":47,"temp_min":293.15,"temp_max":298.15},"wind":{"speed":5.1,"deg":340},"clouds":{"all":0},"dt":1406664059,"id":2643743,"name":"London","cod":200}'
$jsmn = Jsmn_Decode($json1)

$object = Jsmn_ObjGet($jsmn, "coord")
$keys = Jsmn_ObjGetKeys($object)
_ArrayDisplay($keys)

At this point I get an array with "lun" and "lat".
 
How would I actually get the value of these 2 keys?
 
Additionally, why if I try to get the "weather" key, am I not getting any return?
 
 
Thank you I really appreciate the hard work you guys put into developing these UDF's.

Edited by tes5884

Share this post


Link to post
Share on other sites
Ward

To get value in object, just use Jsmn_ObjGet.

In your json, weather is an array, and array[0] is an object.

After you got $jsmn object decoded from the $json1 string, try this code.

$coord = Jsmn_ObjGet($jsmn, "coord")
ConsoleWrite(Jsmn_ObjGet($coord, "lon") & @LF)
ConsoleWrite(Jsmn_ObjGet($coord, "lat") & @LF)

$weather = Jsmn_ObjGet($jsmn, "weather")
For $key In $weather[0]
    ConsoleWrite(StringFormat("%s => %s\n", $key, Jsmn_ObjGet($weather[0], $key)))
Next

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

 

Share this post


Link to post
Share on other sites
tes5884

 

To get value in object, just use Jsmn_ObjGet.

In your json, weather is an array, and array[0] is an object.

After you got $jsmn object decoded from the $json1 string, try this code.

$coord = Jsmn_ObjGet($jsmn, "coord")
ConsoleWrite(Jsmn_ObjGet($coord, "lon") & @LF)
ConsoleWrite(Jsmn_ObjGet($coord, "lat") & @LF)

$weather = Jsmn_ObjGet($jsmn, "weather")
For $key In $weather[0]
    ConsoleWrite(StringFormat("%s => %s\n", $key, Jsmn_ObjGet($weather[0], $key)))
Next

That worked. Thank you!

Share this post


Link to post
Share on other sites
poolcat

In case you're feeling lost, here's a little helper function that lists up all accessible items // based on ward's cool stuff. Cheers

#include "JSMN.au3"
#include <array.au3>
#include <file.au3>

Local $filelist = _FileListToArray(@ScriptDir, "*.json")
Local $i, $json, $obj

For $i = 1 To $filelist[0]
    ConsoleWrite("-----------" & $filelist[$i] & "----------------" & @CRLF)
    $json = FileRead($filelist[$i])
    $obj = Jsmn_Decode($json)
    Jsmn_Iterate($obj, '', $filelist[$i])
Next

Func Jsmn_Iterate($obj, $string, $pre = "")
    Local $temp, $i, $b

    If ($pre <> "") Then ConsoleWrite($pre & ": ")

    $a = Jsmn_Get_ShowResult($obj, $string)
    If IsArray($a) Then
        For $i = 0 To UBound($a) - 1
            Jsmn_Iterate($obj, $string & '[' & $i & ']', $pre)
        Next
    ElseIf IsObj($a) Then
        $b = Jsmn_ObjGetKeys($a)
        For $temp In $b
            Jsmn_Iterate($obj, $string & '["' & $temp & '"]', $pre)
        Next
    EndIf
    Return
EndFunc   ;==>Jsmn_Iterate

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
    Return $Ret
EndFunc   ;==>Jsmn_Get_ShowResult

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   ;==>Jsmn_Get
Edited by poolcat

Share this post


Link to post
Share on other sites
Ward

== Update 2015/01/08 ==
* Rename the library from jsmn.au3 to json.au3. All function names are changed, too.
* Add Json_Put() and Json_Get()
* Add Null support
* Using BinaryCall.au3 to loading the machine code.


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

 

Share this post


Link to post
Share on other sites
argumentum

 

In case you're feeling lost, here's a little helper function that lists up all accessible items // based on ward's cool stuff. Cheers

#include "JSMN.au3"

Thanks much for your code. I touch up your code to work with the new UDF.

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

Local $filelist = _FileListToArray(@ScriptDir, "*.json")
Local $i, $json, $obj

For $i = 1 To $filelist[0]
    ConsoleWrite("-----------" & $filelist[$i] & "----------------" & @CRLF)
    $json = FileRead($filelist[$i])
    $obj = Json_Decode($json)
    Json_Iterate($obj, '', $filelist[$i])
Next

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

Func Json_Get_ShowResult($Var, $Key)
    Local $Ret = Json_Getr($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
    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

So my problem is solved.

Edited by argumentum

Share this post


Link to post
Share on other sites
mojomatt

Need some help getting values out of this JSON.  Any ideas on how to access the value "ThisIsWhatIWant"...?

Here's my json...

{ 
"Headers":[ 
{ 
"Name":"LOGICAL_NAME",
"Type":"VARCHAR2"
}
],
"ColumnCount":1,
"Rows":[ 
{ 
"Cells":[ 
"ThisIsWhatIWant"
],
"CellCount":1
}
]
}

And this is my non-working code attempt...

#include <JSon.au3>

$Json1 = '{ "Headers":[ { "Name":"LOGICAL_NAME","Type":"VARCHAR2"}],"ColumnCount":1,"Rows":[ { "Cells":[ "ThisIsWhatIWant"],"CellCount":1}]}'

Local $objJson = Json_Decode($Json1)
If (json_IsObject($objJson)) Then

;~ ConsoleWrite('Data1:' & json_ObjGetKeys($objJson) & @CRLF)
ConsoleWrite('Data2:' & json_ObjGet($objJson, "ColumnCount") & @CRLF);this line just to prove I can access something
ConsoleWrite('Data2:' & json_ObjGet($objJson, '["Rows"]["Cells"]') & @CRLF)
ConsoleWrite('Data2:' & json_ObjGet($objJson, '["Rows"][0]["Cells"]') & @CRLF)
ConsoleWrite('Data2:' & json_ObjGet($objJson, "['Rows']['Cells']") & @CRLF)
ConsoleWrite('Data2:' & json_ObjGet($objJson, '["Rows"]["Cells"]') & @CRLF)
ConsoleWrite('Data2:' & json_ObjGet($objJson, '["Rows"][0]["Cells"]') & @CRLF)
ConsoleWrite('Data2:' & json_ObjGet($objJson, "Rows.Cells[1]") & @CRLF)
ConsoleWrite('Data2:' & json_ObjGet($objJson, '["Rows"][0]["Cells"]') & @CRLF)
 ConsoleWrite('Data3:' & json_ObjGetCount($objJson) & @CRLF)
  ConsoleWrite('Data4:' & json_ObjExists($objJson, "Rows") & @CRLF)
Else
    ConsoleWrite("no an object")
EndIf

Thanks

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

    • jesus40
      By jesus40
      Hello friends, I need help getting data from json. I read json from url into a variable.
      Is possible to get volume_USD value etc.  where product_id= "ETH-BTC", ? So I want get "37421.69109185" as variable.
      I think is better keeping it in the memory as variable. Or easier to convert it to db or csv?
       
       
      #include <Inet.au3> #include <json.au3> $URL="https://api.abucoins.com/products/stats" $data = _INetGetSource($URL) MsgBox("","",$data) $object=json_decode($data) local $i=0 while 1 $message=json_get($object,'[product_id]');???????????????????????????????? MsgBox("","volume_USD",$message) $i=$i+1 WEnd  
      the json structure is here:
      https://api.abucoins.com/products/stats
      [ { "product_id": "ETH-BTC", "last": "0.05202015", "open": "0.05009375", "high": "0.05250000", "low": "0.04872420", "volume": "47.77440456", "volume_BTC": 2.48523169, "volume_USD": 37421.69109185, "volume_7d": "364.40240341", "volume_30d": "3555.83377072", "change": "3.85" }, { "product_id": "LTC-BTC", "last": "0.01737490", "open": "0.01744636", "high": "0.01779000", "low": "0.01658091", "volume": "67.62762830", "volume_BTC": 1.17502328, "volume_USD": 17941.95920676, "volume_7d": "611.57893068", "volume_30d": "3881.57766044", "change": "-0.41" }, { "product_id": "ETC-BTC", "last": "0.00191846", "open": "0.00189001", "high": "0.00198000", "low": "0.00162741", "volume": "66.48327742", "volume_BTC": 0.12754551, "volume_USD": 1947.54976323, "volume_7d": "738.94495089", "volume_30d": "4090.74712156", "change": "1.51" }, { "product_id": "ZEC-BTC", "last": "0.03466163", "open": "0.03365452", "high": "0.03466163", "low": "0.03295811", "volume": "33.40101560", "volume_BTC": 1.15773364, "volume_USD": 17677.95599574, "volume_7d": "191.15953471", "volume_30d": "887.70158297", "change": "2.99" } ]  
       
    • satanico64
      By satanico64
      hi guys !
      how are you ? fine ? yeahhh
      Here is my problem:
      I have 2 autoit applications, a.exe and b.exe
      In a.exe, i call b.exe with a json as parameter:
      FileWrite("N:\+++ Dev\ClientServeur\FolderMonitor.nca", "lejson in A:" & Json_Encode($json_tmp)& @CRLF) Run(@ScriptDir & "\FolderMonitor.exe " & Json_Encode($json_tmp) )                        
              In program B:
      ;Firstline of program: FileWrite("N:\+++ Dev\ClientServeur\FolderMonitor.nca", @CRLF & "json in B:" & $CmdLine[1] & @CRLF)        
              Output:
                     
              lejson in A:{"DOSSIERS":{"Dossier_Hidden":"N:\\+++ Dev\\ClientServeur\\","Dossier_du_script":"N:\\+++ Dev\\ClientServeur\\","Fichier_Historique":"N:\\+++ Dev\\ClientServeur\\Historique.log","Fichier_DEBUG":"N:\\+++ Dev\\ClientServeur\\FolderMonitor.nca"}}
              json in B  :{DOSSIERS:{Dossier_Hidden:N:\\+++ Dev\\ClientServeur\\,Dossier_du_script:N:\\+++ Dev\\ClientServeur\\,Fichier_Historique:N:\\+++ Dev\\ClientServeur\\Historique.log,Fichier_DEBUG:N:\\+++ Dev\\ClientServeur\\FolderMonitor.nca}}
      As you see, i lost my quote in my json so it's au problem to parse my json.
      I use THIS library
      I tried different type of encoding (ex JSON_STRICT_PRINT), but i don't think that it's the problem. Maybe i'm wrong
       
      thanks
      Nicolas.
    • jandings
      By jandings
      Hello there,
      since I spent some time to access the REST-API of the web shop system Shopware, I'd like to share a few lines to make life easier for others.
      With this you can access your Shopware database, reading and writing all kind of data. 
      Replies are JSON style.
      To work with JSON I usually depend on either just own AutoIt string operations or this AutoIt library:
      ; File        : Json.au3 (2015.01.08)
      ; Purpose    : A Non-Strict JavaScript Object Notation (JSON) Parser UDF
      ; Author    : Ward
      $UserName="xxxx" ;Shopware credentials of Shopware user who has the API checkbox ticked $PassWord="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ;API-Key of this user, NOT the Password $URL="www.XXX.com/api/" $Command="orders/64682?useNumberAsId=true" ;A list of commands and options is available through shopware REST-API help; Here we read order number 64682 $oHTTP = ObjCreate("winhttp.winhttprequest.5.1") $oHTTP.Open("GET", "https://" & $URL & $Command , False) $oHTTP.SetCredentials($UserName, $PassWord, 0) $oHTTP.Send() $response = $oHTTP.ResponseText ConsoleWrite ($response & @CRLF & @CRLF)  
    • BJP
      By BJP
      Hello.  I have a program that has used ADO database connection to return a query and then subsequently put the query results into an array using getrows.  See snippet below:
      $constrim="DRIVER={SQL Server};SERVER=xxx-xxxxx\CSC;DATABASE=xxxxxxxxx;uid=xxxxxxxxxx;pwd=xxxxxxxxxxxx;" $adCN = ObjCreate ("ADODB.Connection") ; <== Create SQL connection $adCN.Open ($constrim) ; local $sQuery = "select * from tbl_Apps"                     ; get all applications in the database local $oAppRecordSet = $adCN.Execute($sQuery) local $aAppsInDB = $oAppRecordSet.Getrows(5000) With the code above I can perform array operations very efficiently. 
      Now I need to get this data via JSON which is working (using Ward's JSON UDF)  but the data set returned is large (approx 4MB) and I'm wondering what is the most efficient way to get this data into an array.  
      Dim $obj = ObjCreate ("WinHttp.WinHttpRequest.5.1") $obj.Open("GET", $URL, false) $obj.SetRequestHeader("Content-Type", "application/json") $obj.Send() $json = JSON_decode( $obj.ResponseText ) Any help would be appreciated!!
    • baolo073
      By baolo073
      [ [ [ "Kinh Oanh,\r\n", "Dear Oanh,\r\n", null, null, 3 ], [ "C\u1ea3m \u01a1n b\u1ea1n r\u1ea5t nhi\u1ec1u v졢\u1ee9c th\u01b0 c\u1ee7a b\u1ea1n \u0111\u1ebfn m\u1ed9t v᩠ngṠtr\u01b0\u1edbc. ", "Thank you very much for your letter which arrived a few days ago.", null, null, 3 ], [ "Th\u1eadt \u0111⯧ y뵠khi nghe t\u1eeb b\u1ea1n.\r\n", "It was lovely to hear from you.\r\n", null, null, 3 ], [ "b\u1ea1n \u0111i \u0111㵠v\u1eady.\r\n", "where do you go.\r\n", null, null, 1 ], [ "T\u1ea1m bi\u1ec7t!", "Goodbye!", null, null, 1 ] ], null, "en", null, null, null, 0.91366601, null, [ [ "en" ], null, [ 0.91366601 ], [ "en" ] ] ] How to parse array to json?
×