Jump to content

A Non-Strict JSON UDF (JSMN)


Ward
 Share

Recommended Posts

Happy New Year :)!

I have very often problems like that:

Quote

"C:\PROGRA~2\AutoIt3\Include\Json.au3" (351) : ==> Variable must be of type "Object".:
Return $Object.Keys()
Return $Object^ ERROR

Is there a way to easy find the calling point in my script? I use a lot of "Json_ObjGetKeys()" and I would like to find the reason, why I sometimes dont get an object at this part. How do you debug this in a good way :)?

I could secure it with lots of "Json_ObjExists()", but maybe I should have an object there and my code isnt stable enough.

Edited by Acanis
Link to comment
Share on other sites

@Acanis Generally you would want to implement error checking in your code as much as possible, so that your script does't stop because of an error like that. There is no easy way (as far as I am aware) to capture these error without getting AutoIt interrupted...

2 hours ago, Acanis said:

but maybe I should have an object there and my code isnt stable enough.

Yes, you are right about this.

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Link to comment
Share on other sites

Should we add a little bit error handling to the UDF?!

Quote

"C:\PROGRA~2\AutoIt3\Include\Json.au3" (343) : ==> Variable must be of type "Object".:
Return $Object.Exists(String($Key))
Return $Object^ ERROR


Every of this could have a for example a "IsObject Else SetError Return".

Link to comment
Share on other sites

  • Developers

I have no issue when more error checking is added to the set of UDF's to avoid it crashing but rather simply returning a error.

Let me know when you are done adding it and simply submit it for including in this set. ;) 

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

Well you need to think about what you want to return and which errorcode to set for each possible mistake. This can then also be documented.
I could imaging that there are many issues that could popup, but the main goal should be that the UDF doesn't crap out whatever you throw at it. :) 
When it all is done well we could even consider making it part of the standard UDF library and create the helpfile pages for it, but first things first. 

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

  • 2 weeks later...

Hi everybody and many thanks for sharing this UDF.
I'm not an expert in programming languages but I'm trying to get some data from an API that is similar to the $json1 of the following code:

#include <json.au3>
$json1 = '{"Global Quote":{"01. symbol" : "MSFT","02. open" : "101.9000","03 high" : "102.8716"}}'
$Json = Json_Decode($json1)
$coord = Json_ObjGet($Json, "Global Quote")
ConsoleWrite(Json_ObjGet($coord, "01. symbol") & @LF)
ConsoleWrite(Json_ObjGet($coord, "03 high") & @LF)

The problem that I'm trying to solve is that the keys of the Json file includes dots (.) and therefore I cannot get the value.
The debug console returns with success the value of the key "03 high" where I've eliminated the dot, while doesn't return any value for the "01. symbol".
I tried to double quote the keys. I also tried to use Json_Get instead of Json_ObjGet but nothing works.

On the other side the Json_Dump shows correctly all the values (for keys with or without dots), but it's too difficult for me to get the solution from the UDF code.

#include <json.au3>
$data = '{"Global Quote":{"01. symbol" : "MSFT","02. open" : "101.9000","03 high" : "102.8716"}}'
Global $object = Json_Decode($data)
ConsoleWrite("!== Json_TokenDump ============================================================================================================" & @CRLF)
Json_Dump($data)



!== Json_TokenDump ============================================================================================================
+-> .Global Quote.01. symbol  =MSFT
+-> .Global Quote.02. open  =101.9000
+-> .Global Quote.03 high  =102.8716
>Exit code: 0    Time: 0.3965


Can anyone kindly give me an hint for this problem?

Link to comment
Share on other sites

  • Developers

I am afraid the current UDF's have a problem reading keys with a dot inside as the dot is use as separator. 

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

There also appears to be a bug with names that begin with a numeric digit.  In the snippet below, the first value gets written out and the second value does not. 

#include <json.au3>

$data = '{"Test" : {"Name01" : "Value01", "02Name" : "Value02"}}'

$oJson = Json_Decode($data)
ConsoleWrite("Value = " & Json_Get($oJson, ".Test.Name01") & @CRLF) ;Displays Value01
ConsoleWrite("Value = " & Json_Get($oJson, ".Test.02Name") & @CRLF) ;Displays <blank>

 

Edited by TheXman
Link to comment
Share on other sites

  • Developers

Try:

ConsoleWrite("Value = " & Json_Get($oJson, '."Test"."02Name"') & @CRLF) ;Displays <blank>

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

Both of the following correctly display the value:

ConsoleWrite("Value = " & Json_Get($oJson, '."Test"."02Name"') & @CRLF)
ConsoleWrite("Value = " & Json_Get($oJson, '.Test."02Name"')   & @CRLF)

For the record, the same is true with bracket notation.  Using '[Test][02Name]' does not work but '[Test]["02Name"]' does work.

 

Edited by TheXman
Link to comment
Share on other sites

2 hours ago, Danp2 said:

@aio Have you tried wrapping the key value in quotation marks?

 

Yes, I did. Also retested with the combinations indicated in following posts from Jos and TheXman

 

2 hours ago, Jos said:

I am afraid the current UDF's have a problem reading keys with a dot inside as the dot is use as separator. 

Jos

Sigh..... I was hoping that there was a solution because of Json_Dump () capable of retrieving all the values.

Anyway there could be also a problem when keys contains a blankspace like in my case ("Global Quote"). See below, answering to TheXman

 

2 hours ago, TheXman said:

Both of the following correctly display the value:

ConsoleWrite("Value = " & Json_Get($oJson, '."Test"."02Name"') & @CRLF)
ConsoleWrite("Value = " & Json_Get($oJson, '.Test."02Name"')   & @CRLF)

For the record, the same is true with bracket notation.  Using '[Test][02Name]' does not work but '[Test]["02Name"]' does work.

 

 

Here is my testing of all combinations using my keys. As far as I understand there could be a bug also when a key contains a blankspace.

#include <json.au3>
$json1 = '{"Global Quote":{"01. symbol" : "MSFT","02. open" : "101.9000","03 high" : "102.8716"}}'
$json1bis = '{"GlobalQuote":{"01. symbol" : "MSFT","02. open" : "101.9000","03 high" : "102.8716"}}'
$json1tris = '{"GlobalQuote":{"01. symbol" : "MSFT","02. open" : "101.9000","03high" : "102.8716"}}'
$Json = Json_Decode($json1)
$Jsonbis = Json_Decode($json1bis)
$Jsontris = Json_Decode($json1tris)
;
ConsoleWrite("CASE 1    -->>   " & Json_Get($Json, '."Global Quote"."03 high"') & @LF)      ; ==>> it works!!
;
ConsoleWrite("CASE 2    -->>   " & Json_Get($Json, '.Global Quote."03 high"') & @LF)        ; ==>> it doesn't work!!
ConsoleWrite("CASE 2bis -->>   " & Json_Get($Jsonbis, '.GlobalQuote."03 high"') & @LF)      ; ==>> it works!!
;
ConsoleWrite("CASE 3    -->>   " & Json_Get($Json, '[Global Quote][03 high]') & @LF)        ; ==>> it doesn't work!!
ConsoleWrite("CASE 3bis -->>   " & Json_Get($Jsonbis, '[GlobalQuote][03 high]') & @LF)      ; ==>> it doesn't work!!
ConsoleWrite("CASE 3tris    -->>   " & Json_Get($Jsontris, '[GlobalQuote][03high]') & @LF)  ; ==>> it doesn't work!!
;
ConsoleWrite("CASE 4    -->>   " & Json_Get($Json, '[Global Quote]["03 high"]') & @LF)      ; ==>> it doesn't work!!
ConsoleWrite("CASE 4bis -->>   " & Json_Get($Jsonbis, '[GlobalQuote]["03 high"]') & @LF)    ; ==>> it works!!

 

Edited by aio
Link to comment
Share on other sites

  • Developers

I am sure this can be fixed, just needs time to invest in modifying the code not testing for dots inside double quoted strings. 

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

On 1/4/2019 at 9:08 AM, Jos said:

we could even consider making it part of the standard UDF library

also, 

Quote

so using @TheXman example:

#include <SQLite.au3>

example()

Func example()
        Const $TEST_JSON = '{"Test" : {"Name01" : "Value01", "02Name" : "Value02", "03 high" : "102.8716"}}'

        Const $SQLITE_DLL = "C:\...\sqlite3.dll" ;<-- Change to the location of your sqlite dll

        Local $aRow
        Local $hQuery

        ;Init sqlite and create a memory db
        _SQLite_Startup($SQLITE_DLL, False, 1)
        If @error Then Exit MsgBox($MB_ICONERROR, "SQLite Error", "Unable to start SQLite. Check existence of DLL")
        _SQLite_Open()

        ;Example of validating json (Good return means JSON is well-formed)
        If _SQLite_Query(-1, "select json('" & $TEST_JSON & "');", $hQuery) = $SQLITE_OK Then
            While _SQLite_FetchData($hQuery, $aRow) = $SQLITE_OK
                ConsoleWrite("Minimized JSON = " & $aRow[0] & @CRLF)
            WEnd
        EndIf

        ;Example of extracting data
        If _SQLite_Query(-1, "select json_extract('" & $TEST_JSON & "', '$.Test.03 high');", $hQuery) = $SQLITE_OK Then
            While _SQLite_FetchData($hQuery, $aRow) = $SQLITE_OK
                ConsoleWrite("03 high = " & $aRow[0] & @CRLF)
            WEnd
        EndIf

        ;Close db and shutdown sqlite
        _SQLite_Close()
        _SQLite_Shutdown()

EndFunc

If there is to be a native AutoIt UDF for JSON, could the SQLite be used for such ? ( just asking )

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

Link to comment
Share on other sites

  • Developers

I've honestly havent looked at that one yet. Just started with this build and added some stuff to make my life easier. :)
I am fine with any good solution so will have a look at that option.

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

Well I couldn't resists trying to fix this set of UDF's so think I am getting close with the attached version:

#include <array.au3>
#include <json.au3>
$json1 = '{"Global Quote":{"01. symbol" : "MSFT","02. open" : "01.10","03 high" : "10.1"}}'
$json1bis = '{"GlobalQuote":{"01. symbol" : "MSFT","02. open" : "02.10","03 high" : "20.2"}}'
$json1tris = '{"GlobalQuote":{"01. symbol" : "MSFT","02.open" : "03.10","03high" : "30.3"}}'
$Json = Json_Decode($json1)
$Jsonbis = Json_Decode($json1bis)
$Jsontris = Json_Decode($json1tris)
;
ConsoleWrite("!===============================================================================" & @crlf)
ConsoleWrite("CASE 1    -->>   " & Json_Get($Json, '."Global Quote"."03 high"') & @LF)      ; ==>> it works!!

ConsoleWrite("CASE 2    -->>   " & Json_Get($Json, '.Global Quote."03 high"') & @LF)        ; ==>> it doesn't work!!
ConsoleWrite("CASE 2bis -->>   " & Json_Get($Jsonbis, '.GlobalQuote."03 high"') & @LF)      ; ==>> it works!!
ConsoleWrite("CASE 2bis2-->>   " & Json_Get($Jsonbis, 'GlobalQuote."03 high"') & @LF)       ; ==>> it doesn't work!!
ConsoleWrite("CASE 2bis3-->>   " & Json_Get($Jsonbis, 'GlobalQuote.03 high') & @LF)       ; ==>> it doesn't work!!
;~ ;
ConsoleWrite("CASE 3    -->>   " & Json_Get($Json, '[Global Quote][03 high]') & @LF)        ; ==>> it doesn't work!!
ConsoleWrite("CASE 3bis -->>   " & Json_Get($Jsonbis, '[GlobalQuote][03 high]') & @LF)      ; ==>> it doesn't work!!
ConsoleWrite("CASE 3tris-->>   " & Json_Get($Jsontris, '[GlobalQuote][03high]') & @LF)      ; ==>> it doesn't work!!
;~ ;
ConsoleWrite("CASE 4    -->>   " & Json_Get($Json, '[Global Quote]["03 high"]') & @LF)      ; ==>> it doesn't work!!
ConsoleWrite("CASE 4bis -->>   " & Json_Get($Jsonbis, '[GlobalQuote]["03 high"]') & @LF)    ; ==>> it works!!;~ ;
;
ConsoleWrite("CASE 1    -->>   " & Json_Get($Json, '."Global Quote"."03 high"') & @LF)      ; ==>> it works!!
ConsoleWrite("CASE 1    -->>   " & Json_Get($Json, '."Global Quote"."02. open"') & @LF)      ; ==>> it works!!

ConsoleWrite("CASE 2    -->>   " & Json_Get($Json, '.Global Quote."02. open"') & @LF)        ; ==>> it doesn't work!!
ConsoleWrite("CASE 2bis -->>   " & Json_Get($Jsonbis, '.GlobalQuote."02. open"') & @LF)      ; ==>> it works!!
ConsoleWrite("CASE 2bis2-->>   " & Json_Get($Jsonbis, 'GlobalQuote."02. open"') & @LF)       ; ==>> it doesn't work!!
;~ ;
ConsoleWrite("CASE 3    -->>   " & Json_Get($Json, '[Global Quote][02. open]') & @LF)        ; ==>> it doesn't work!!
ConsoleWrite("CASE 3bis -->>   " & Json_Get($Jsonbis, '[GlobalQuote][02. open]') & @LF)      ; ==>> it doesn't work!!
ConsoleWrite("CASE 3tris-->>   " & Json_Get($Jsontris, '[GlobalQuote][02.open]') & @LF)      ; ==>> it doesn't work!!
;~ ;
ConsoleWrite("CASE 4    -->>   " & Json_Get($Json, '[Global Quote]["02. open"]') & @LF)      ; ==>> it doesn't work!!
ConsoleWrite("CASE 4bis -->>   " & Json_Get($Jsonbis, '[GlobalQuote]["02. open"]') & @LF)    ; ==>> it works!!;~ ;

Results:

!===============================================================================
CASE 1    -->>   10.1
CASE 2    -->>   10.1
CASE 2bis -->>   20.2
CASE 2bis2-->>   20.2
CASE 2bis3-->>   20.2
CASE 3    -->>   10.1
CASE 3bis -->>   20.2
CASE 3tris-->>   30.3
CASE 4    -->>   10.1
CASE 4bis -->>   20.2
CASE 1    -->>   10.1
CASE 1    -->>   01.10
CASE 2    -->>   01.10
CASE 2bis -->>   02.10
CASE 2bis2-->>   02.10
CASE 3    -->>   01.10
CASE 3bis -->>   02.10
CASE 3tris-->>   03.10
CASE 4    -->>   01.10
CASE 4bis -->>   02.10

@aio and others, could you have a spin with this version to see whether anything is broken?

Jos

Json.au3

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

7 hours ago, Jos said:

Well I couldn't resists trying to fix this set of UDF's so think I am getting close with the attached version:

...............

@aio and others, could you have a spin with this version to see whether anything is broken?

Jos

Json.au3

:) Tested with functions Json_Get and Json_ObjGet.

It works in both functions with dots and blankspaces. Don't know if more extensive tests should be performed to guarantee that everything else still works fine.

@Jos Many thanks and sorry for interrupting your schedule.

 

Link to comment
Share on other sites

  • 1 month later...

Hi guys,

is there another way to add a value to an array objet in a json, without using  ubound like i did here ?

if StringInStr($text,"Case") then
        json_put($js, '["Cases"][' & ubound(json_objget($js,'Cases')) & ']',$text)
    elseif StringInStr($text,"Quote") then
         json_put($js, '["Quotes"][' & ubound(json_objget($js,'Quotes')) & ']',$text)

EndIf


       it works but maybe not the best way to do that...
 

{
    "Cases": [
        " Case 156910"
    ],
    "Quotes": [
        "[READ] Quote 483796",
        "[READ] Quote 440329",
        "[READ] Quote 440238"
    ]
}

thanks

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...