Jump to content

A Non-Strict JSON UDF (JSMN)


Ward
 Share

Recommended Posts

  • Developers

Again it is not about Byref but rather the $jsonfunc being a pointer already in the Main part of the script which is passed to the Func.
It is similar to what happens in this demo script:

Global $jsonfunc =  DllStructCreate("char txt[128]")
DllStructSetData($jsonfunc, "txt", "aaa")

Func myfunc($jsonparam)
    ConsoleWrite('+Before $jsonfunc  txt = ' & DllStructGetData($jsonfunc, 1) & @CRLF ) ;### Debug Console
    ConsoleWrite(' Before $jsonparam txt = ' & DllStructGetData($jsonparam, 1) & @CRLF ) ;### Debug Console
    DllStructSetData($jsonfunc, "txt", "bbb")
    ConsoleWrite('-After  $jsonfunc  txt = ' & DllStructGetData($jsonfunc, 1) & @CRLF ) ;### Debug Console
    ConsoleWrite(' After  $jsonparam txt = ' & DllStructGetData($jsonparam, 1) & @CRLF ) ;### Debug Console
EndFunc   ;==>myfunc

myfunc($jsonfunc)

Does that make sense?

Jos

Edited by Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

thanks for your answer

in fact, not really clear for me, why my $jsonparam would be a pointer, function parameters must be in local scope,  they should'nt point to the variable used when we call a function.

In fact with string variables, scope is local, with json, we can't be in local scope and use json as parameter this is what i understand

Your script only with numbers do as i expect:

Global $jsonfunc =  DllStructCreate("char txt[128]")
DllStructSetData($jsonfunc, "txt", "aaa")

Func myfunc($jsonparam)
    ConsoleWrite('+Before $jsonfunc  txt = ' & DllStructGetData($jsonfunc, 1) & @CRLF ) ;### Debug Console
    ConsoleWrite(' Before $jsonparam txt = ' & DllStructGetData($jsonparam, 1) & @CRLF ) ;### Debug Console
    DllStructSetData($jsonfunc, "txt", "bbb")
    ConsoleWrite('-After  $jsonfunc  txt = ' & DllStructGetData($jsonfunc, 1) & @CRLF ) ;### Debug Console
    ConsoleWrite(' After  $jsonparam txt = ' & DllStructGetData($jsonparam, 1) & @CRLF ) ;### Debug Console
EndFunc   ;==>myfunc

myfunc($jsonfunc)

Global $varfunc =  10
Func myfunc2($varparam)
    ConsoleWrite('+Before $varfunc  txt = ' & $varfunc & @CRLF ) ;### Debug Console
    ConsoleWrite(' Before $varparam txt = ' & $varparam & @CRLF ) ;### Debug Console
    $varfunc = 5
    ConsoleWrite('+Before $varfunc  txt = ' & $varfunc & @CRLF ) ;### Debug Console
    ConsoleWrite(' Before $varparam txt = ' & $varparam & @CRLF ) ;### Debug Console
EndFunc   ;==>myfunc
myfunc2($varfunc)

Output:
+Before $jsonfunc  txt = aaa
 Before $jsonparam txt = aaa
-After  $jsonfunc  txt = bbb
 After  $jsonparam txt = bbb
+Before $jsonfunc  txt = 10
 Before $jsonparam txt = 10
+Before $jsonfunc  txt = 5
 Before $jsonparam txt = 10
[edit: variables names corrected in code]

Edited by satanico64
Link to comment
Share on other sites

  • Developers

As I mentioned: 

35 minutes ago, Jos said:

it is not about Byref but rather the $jsonfunc being a pointer already

So $jsonfunc is a pointer to the memory location of the structure ( in your case the Object).
The pointer (hex value) is passed on to Myfunc() via the parameter, but is is still the same value for the pointer, so $jsonparam will then point to the exact same memory location.
That is why, when one changes the other changes as well since they both use the same memory location.

Making more sense now? :) 

Jos

Edited by Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

1 hour ago, TheXman said:

I'm not exactly sure how AutoIt works in this regard without testing it, but in other languages, objects are passed ByRef.  Therefore, if the same holds true you aren't using a copy of the $jsonfunc object in myfunc(), you are using/manipulating the object itself.

For the record, when I used the term "ByRef" above, I was not referring to the keyword ByRef.  It was just my shorthand way of saying "by reference", in other words using a pointer.  :)

Link to comment
Share on other sites

  • Developers
4 minutes ago, TheXman said:

For the record, when I used the term "ByRef" above, I was not referring to the keyword ByRef.  It was just my shorthand way of saying "by reference", in other words using a pointer.  :)

Understand, but just wanted to avoid confusion.
All that Byref would do is created a PTR ($jsonparam) to a PTR ($jsonfunc) which obviously still point to the same memory space, hence my comment it being  a mute point. :) 

Jos

Edited by Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

First of all, sorry for being tenacious, i am really impressed by the whole work that the autoit team does here, so i really take my time before responding and i'm gratefull for you to take time. o:)

But in fact, i still disagree :)   (sorry for that)

The problem here, is that is seems that the parameter passed, is a pointer to the json passed when we call the function. I agree with that... but why ?

 It is not the case when called with a string variable ... You must agree that, for a same function, we do not have the same result, depending of the type of parameter passed. (string or json.. for example). I do not understand why it would be normal.

 

$json param point to the same memory allocation that $jsonfunc,  why ?

A function parameter MUST be in local scope, so it should allocate memory et duplicate data not point to the variable (something like that).  Am i wrong ?

Nicolas
[Edit: adding signature and my prettiest smileys :) ]

Edited by satanico64
Link to comment
Share on other sites

  • Developers
6 minutes ago, satanico64 said:

But in fact, i still disagree :)   (sorry for that)

... and that is fine, but it is what it is.  ;)   

Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

  • 1 month later...

I just downloaded 

Quote

and file Json.au3 first line says:

Quote

; File        : Json.au3 (2015.01.08)

are you sure you uploaded right version?

you also said you fixed Au3Check warnings

On 7.02.2013 at 12:11 PM, Ward said:

== Update 2018/10/01b==   (Jos)
* Added Json_ObjGetItems, Tidied source and fixed au3check warnings - tnx @TheXman .

== Update 2018/10/28==   (Jos)
* Added declaration for $value to avoid au3check warning - tnx @DerPensionist

but I still see one:

Przechwytywanie.JPG.4c87baf4eff41691490a70e4c4d83ff0.JPG

Link to comment
Share on other sites

  • Developers

Thanks for the report ... I've update the file and made a new update available in the first post. :)

Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

  • 2 weeks later...

Hey, uh... Its fast, very nice and thank you :)!

Can I use Json_ObjGet through several "levels"? I have a JSON with Object>Object>Object>Object>Object>Object>Array and I want to get the Array behind all the know objects. Do I need 6x Json_ObjGet or how do I adress that more simple? :)

Thanks

 

*edit*

Json_Dump is showing me "." as seperator between the objects, but with

        Local $oTest = Json_ObjGet($oTemp, 'd.1')
        $aTest = Json_ObjGetItems($oTest)

Local $oTest = Json_ObjGet($oTemp, 'd.1')
        $aTest = Json_ObjGetItems($oTest)
        _ArrayDisplay($aTest)

I get "==> Variable must be of type "Object".:"

If i just use 'd', its working, so the seperator isnt right, or maybe its not possitble?

Edited by Acanis
Link to comment
Share on other sites

  • Developers
19 minutes ago, Acanis said:

Ah, Json_Dump helped me understanding the formatting, still not sure, how I do check, if there is a special string in an array behind 6 objects.

Post an example JSON data, the script you have that isn't working yet and an exact explanation of what you want so we can have a look.

Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

13 minutes ago, Jos said:

Post an example JSON data, the script you have that isn't working yet and an exact explanation of what you want so we can have a look.

Jos

Hey,

Iam looking for a short way to do something like this:

$sJson = ClipGet()
$oTemp = Json_Decode($sJson)

If Json_IsObject($oTemp) Then
    $oTemp1 = Json_ObjGet($oTemp, "d")
    $oTemp2 = Json_ObjGet($oTemp1, "5")
    $oTemp3 = Json_ObjGet($oTemp2, "4")
    $oTemp4 = Json_ObjGet($oTemp3, "6")
    MsgBox(4096, "", Json_ObjExists($oTemp4, "h") & @CRLF)
EndIf

("h" is an array, which holds some informations)

Can "Json_ObjGet" do this in 1 line? Like

$oObject = Json_ObjGet($oTemp, "d.5.4.6")

Thanks :) 

Link to comment
Share on other sites

  • Developers

I am missing some test data to play with. ;)

Simply change the first line and put the actual JSON data there.

 

Edited by Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

48 minutes ago, Jos said:

I am missing some test data to play with. ;)

Simply change the first line and put the actual JSON data there.

 

Sorry, I thoughts that if its possible, it would be easier to see the code. I created a short example:

#include <Json.au3>
#include <Array.au3>

$sJson = '{'& _
            '"d": {' & _
                '"5": {' & _
                    '"4": {' & _
                        '"6": {' & _
                            '"h": [' & _
                                '{' & _
                                    '"id": "1286",' & _
                                    '"status": "sunny",' & _
                                    '"earth": true' & _
                                '}' & _
                            ']' & _
                        '}' & _
                    '}' & _
                '}' & _
            '}' & _
        '}'

$oTemp = Json_Decode($sJson)

If Json_IsObject($oTemp) Then
    $oTemp1 = Json_ObjGet($oTemp, "d")
    $oTemp2 = Json_ObjGet($oTemp1, "5")
    $oTemp3 = Json_ObjGet($oTemp2, "4")
    $oTemp4 = Json_ObjGet($oTemp3, "6")

    If Json_ObjExists($oTemp4, "h") Then
        Local $aH = Json_ObjGet($oTemp4, "h")

        For $i = 0 To Ubound($aH) - 1
            $iID = Json_ObjGet($aH[$i], "id")
            ConsoleWrite($iID & @CRLF)
        Next

    EndIf
EndIf

I want to check, if there is a "h"-object in d > 5 > 4 > 6 and if yes, get for example all the ids. Iam curious, if I need all the "temp"-objects. Maybe there is a notation for Json_ObjGet, that is doing this in less lines. :)

 

Thank you

Edited by Acanis
Link to comment
Share on other sites

  • Developers

mmm... don't think that is possible yet.
Maybe we should add a recursive check to Json_ObjGet() and Json_ObjExists() like this:

#include <Json.au3>
$sJson = '{"d": {"5": {"4": {"6": {"h": [{"id": "1286","status": "sunny","earth": true}]}}}}}'
Json_dump($sJson)
$oTemp = Json_Decode($sJson)
If Json_IsObject($oTemp) Then
    ConsoleWrite('@@ Json_ObjExists($oTemp, "d") = ' & Json_ObjExistsR($oTemp, "d") & @CRLF) ;### Debug Console
    ConsoleWrite('@@ Json_ObjExists($oTemp, "d.5") = ' & Json_ObjExistsR($oTemp, "d.5") & @CRLF) ;### Debug Console
    ConsoleWrite('@@ Json_ObjExists($oTemp, "d.5.4") = ' & Json_ObjExistsR($oTemp, "d.5.4") & @CRLF) ;### Debug Console
    ConsoleWrite('@@ Json_ObjExists($oTemp, "d.5.4.6") = ' & Json_ObjExistsR($oTemp, "d.5.4.6") & @CRLF) ;### Debug Console
    ConsoleWrite('@@ Json_ObjExists($oTemp, "d.5.4.6.h") = ' & Json_ObjExistsR($oTemp, "d.5.4.6.h") & @CRLF) ;### Debug Console
    ConsoleWrite('@@ Json_ObjExists($oTemp, "d.5.4.6.x") = ' & Json_ObjExistsR($oTemp, "d.5.4.6.x") & @CRLF) ;### Debug Console
    $oTempb = Json_ObjGetR($oTemp, "d.5.4.6.h")
    ConsoleWrite('@@ json_get($oTempb,''[0].id'') = ' & json_get($oTempb, '[0].id') & '         >Error code: ' & @error & @CRLF) ;### Debug Console
    $oTempb = Json_ObjGetR($oTemp, "d.5.4.6.x")
    ConsoleWrite('@@ json_get($oTempb,''[0].id'') = ' & json_get($oTempb, '[0].id') & '         >Error code: ' & @error & @CRLF) ;### Debug Console
EndIf

Func Json_ObjExistsR(ByRef $Object, $Key)
    Local $DynObject = $Object
    Local $Keys = StringSplit($Key, ".")
    For $x = 1 To $Keys[0]
        If $DynObject.Exists($Keys[$x]) Then
            If $x = $Keys[0] Then
                Return True
            Else
                $DynObject = Json_ObjGet($DynObject, $Keys[$x])
            EndIf
        Else
            Return False
        EndIf
    Next
    Return $Object.Exists(String($Key))
EndFunc   ;==>Json_ObjExistsR


Func Json_ObjGetR(ByRef $Object, $Key)
    Local $DynObject = $Object
    Local $Keys = StringSplit($Key, ".")
    For $x = 1 To $Keys[0]
        If $DynObject.Exists($Keys[$x]) Then
            If $x = $Keys[0] Then
                Return $DynObject.Item($Keys[$x])
            Else
                $DynObject = Json_ObjGet($DynObject, $Keys[$x])
            EndIf
        EndIf
    Next
    Return SetError(1, 0, '')
EndFunc   ;==>Json_ObjGetR

Thoughts?

Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

  • Developers

Updated the first page with the changed UDFs in the JSON.au3 include.

Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
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
 Share

×
×
  • Create New...