Ward

A Non-Strict JSON UDF (JSMN)

102 posts in this topic

#61 ·  Posted (edited)

On 1/24/2016 at 5:23 AM, Jury said:

Attached is an example of my data - it takes some time but then the end is an array of over 20,000  lines.

I felt bad for the time JsonArrayfied took to do it's work. So I wrote something different that may be useful to you.

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

Local $t = TimerInit()
Local $sJson_3 = FileRead("cma-cases.json")
ConsoleWrite('--- FileRead : ' & TimerDiff($t) / 1000 & ' secs.' & @CRLF)
$t = TimerInit()
Local $Data2 = Json_Decode($sJson_3)
ConsoleWrite('--- Json_Decode : ' & TimerDiff($t) / 1000 & ' secs.' & @CRLF)
$t = TimerInit()
Local $Json3 = Json_Encode($Data2, $Json_PRETTY_PRINT, "\t", "\n", "\n")
ConsoleWrite('--- Json_Encode : ' & TimerDiff($t) / 1000 & ' secs.' & @CRLF)
;~ ConsoleWrite($Json3 & @CRLF)
$t = TimerInit()
Local $aOut = Json_Encode_Array_v1($Json3)
ConsoleWrite('--- Json_Encode_Array : ' & TimerDiff($t) / 1000 & ' secs.' & @CRLF)
_ArrayDisplay($aOut, "Json_Encode_Array")

Func Json_Encode_Array_v1($sJsonPrettyPrint)
    Local $n, $m, $aJsonPrettyPrint = StringSplit($sJsonPrettyPrint, @LF)
    Local $iArrayColumns = 20
    Local $aOut[UBound($aJsonPrettyPrint) + 1][$iArrayColumns]
;~  Local $aCounter[$iArrayColumns + 1]
;~  For $n = 0 To $iArrayColumns ; for future use
;~      $aCounter[$n] = 0        ; will use in v2 of this function ( if I ever get to do it )
;~  Next                         ; to add the array and object count as in JsonArrayfied()
    Local $b, $c, $i = 0, $iArrayMaxColumnsUsed = 0
    For $n = 1 To $aJsonPrettyPrint[0]
        $b = StringSplit($aJsonPrettyPrint[$n], @TAB)
        $c = StringSplit($b[$b[0]], '":', 1)
        $i += 1
        Switch StringStripWS($aJsonPrettyPrint[$n], 8)
            Case "{"
                $aOut[$i][0] = "ObjectStart"
                $aOut[$i][Int($b[0] / 2) + 1] = "{"
                ContinueLoop
            Case "}"
                $aOut[$i][0] = "ObjectEnd"
                $aOut[$i][Int($b[0] / 2) + 1] = "}"
                ContinueLoop
            Case "]"
                $aOut[$i][0] = "ArrayEnd"
                $aOut[$i][Int($b[0] / 2) + 1] = "]"
                ContinueLoop
        EndSwitch
        $c[2] = StringTrimLeft($c[2], 1)
        $aOut[$i][Int($b[0] / 2)] = StringTrimLeft($c[1], 1)
        $aOut[$i][Int($b[0] / 2) + 1] = $c[2]
        If Int($b[0] / 2) > $iArrayMaxColumnsUsed Then $iArrayMaxColumnsUsed = Int($b[0] / 2)
        If $c[2] = "[" Then
            $aOut[$i][0] = "ArrayStart"
            ContinueLoop
        EndIf
        If StringInStr($c[2], '"') Then
            $aOut[$i][0] = "String"
        ElseIf $c[2] = "{" Then
            $aOut[$i][0] = "ObjectStart"
        ElseIf $c[2] = "}" Then
            $aOut[$i][0] = "ObjectEnd"
        ElseIf $c[2] = "{}" Then
            $aOut[$i][0] = "ObjectEmpty"
        ElseIf $c[2] = "[" Then
            $aOut[$i][0] = "ArrayStart"
        ElseIf $c[2] = "]" Then
            $aOut[$i][0] = "ArrayEnd"
        ElseIf $c[2] = "[]" Then
            $aOut[$i][0] = "ArrayEmpty"
        ElseIf $c[2] = "null" Then ; http://www.tutorialspoint.com/json/json_data_types.htm
            $aOut[$i][0] = "Null"  ; http://stackoverflow.com/questions/8204578/what-is-the-type-of-null-literal
        ElseIf $c[2] = "true" Or $c[2] = "false" Then
            $aOut[$i][0] = "Bool"
        Else
            $aOut[$i][0] = "Number"
        EndIf
    Next
    $aOut[0][0] = $i
    $aOut[0][1] = $iArrayMaxColumnsUsed + 1
    ReDim $aOut[$i + 1][$iArrayMaxColumnsUsed + 2]
    Return $aOut
EndFunc   ;==>Json_Encode_Array_v1

try it out. It's way faster.
Edit: I just now realized that it works fine with your json but not with other json, so use it as an example of something faster but that is all.

Edited by argumentum

Share this post


Link to post
Share on other sites



Hi

 

Sorry for disturbing, but I had no luck to find the  jsmn.au3 or json.au3 file to download. All possibilites are striked through / underlined and led to an empty page (the first pages links) . Am I this blind?

Share this post


Link to post
Share on other sites

Hi
Thanks for the quick replay, I read through, but somehow I missed it.
I'm not a Json master (nor XML), so I stucked. Its a really basic text, but I can't get a simple data from it.
 

#Include "Json.au3"

;Two text, the $Json_simplest is just for technical reason
Local $Json = "{'status':'ok','meta':{'count':1},'data':{'519937860':{'statistics':{'all':{'battles':1398}}}}}"
Local $Json_simplest = "{'battles':1398}"

;Decode with UDF
Local $Obj = Json_Decode ($Json)
Local $Obj_simplest  = Json_Decode ($Json_simplest)

;Basic querys, with empty data given back
ConsoleWrite( "status:" & Json_Get  ($Obj, '[status]') & @LF)
ConsoleWrite( "battles:" & Json_Get ($Obj, '[data][519937860][statistics][all][battles]') & @LF)

;Simplest basic query
ConsoleWrite( "battles_simplest:" & Json_Get ($Obj_simplest, '[battles]') & @LF)

What the good code looks like? I couldn't find tutorial for json querys.

Share this post


Link to post
Share on other sites
3 hours ago, szocsmarci said:

Hi
Thanks for the quick replay, I read through, but somehow I missed it.
I'm not a Json master (nor XML), so I stucked. Its a really basic text, but I can't get a simple data from it.
 

#Include "Json.au3"

;Two text, the $Json_simplest is just for technical reason
Local $Json = "{'status':'ok','meta':{'count':1},'data':{'519937860':{'statistics':{'all':{'battles':1398}}}}}"
Local $Json_simplest = "{'battles':1398}"

;Decode with UDF
Local $Obj = Json_Decode ($Json)
Local $Obj_simplest  = Json_Decode ($Json_simplest)

;Basic querys, with empty data given back
ConsoleWrite( "status:" & Json_Get  ($Obj, '[status]') & @LF)
ConsoleWrite( "battles:" & Json_Get ($Obj, '[data][519937860][statistics][all][battles]') & @LF)

;Simplest basic query
ConsoleWrite( "battles_simplest:" & Json_Get ($Obj_simplest, '[battles]') & @LF)

What the good code looks like? I couldn't find tutorial for json querys.

;Simplest basic query
ConsoleWrite( "battles_simplest:" & Json_Get ($Obj_simplest, "['battles']") & @LF) ; not much of a difference, use ConsoleWriteJson($Obj_simplest) to get what you need, ConsoleWriteJson is posted somewere in my signature.

 

Share this post


Link to post
Share on other sites

#67 ·  Posted (edited)

Thanks a lot, it works.

Curious thing the apostrophs.

#Include "Json.au3"

 Local $text1 = '{"status":"ok","meta":{"count":1},"data":{"519937860":{"statistics":{"all":{"battles":1404}}}}}'
 Local $Obj1 = Json_Decode ($text1)
 Local $battles1 = Json_Get ($Obj1, '["data"]["519937860"]["statistics"]["all"]["battles"]')
 ConsoleWrite( "battles Text1:" & $battles1 & @LF)

 Local $text2 = "{'status':'ok','meta':{'count':1},'data':{'519937860':{'statistics':{'all':{'battles':1404}}}}}"
 Local $Obj2 = Json_Decode ($text2)
 Local $battles2 = Json_Get ($Obj2, "['data']['519937860']['statistics']['all']['battles']")
 ConsoleWrite( "battles Text2:" & $battles2 & @LF)

See the " and the ' swapping in the origin text and the Json_Get query.

Edited by szocsmarci
1 person likes this

Share this post


Link to post
Share on other sites

I'd like to get some help from Json experts.

I want to add some Json data into my json file. For example, mydata.json = [{"data":"apple","weight":"180"}]. I want to add some data in this json file such as {"data":"graph", "weight":"100"}. my result json data is mydata.json = [{"data":"apple","weight":"180"},{"data":"graph", "weight":"100"}].

 

Share this post


Link to post
Share on other sites

#69 ·  Posted (edited)

i'm experimenting with a json file. with this code i can get individual cell values:

ConsoleWrite(Json_Get($Obj, '["aaData"][0]["date"]') & @LF)
ConsoleWrite(Json_Get($Obj, '["aaData"][0]["status"]') & @LF)
ConsoleWrite(Json_Get($Obj, '["aaData"][0]["amount"]') & @LF)

 

but how do i loop through if the number of rows is unknow? 

Tried first getting the "aaData" object but not sure how make a loop!?

 

I can use this code to determ how many items are in each row, but i need to know the number of rows to loop through them?

$myarray = (Json_Get($Obj, '["aaData"][0]'))
ConsoleWrite(Json_ObjGetCount($myarray))

$myarray = (Json_Get($Obj, '["aaData"][0]'))
ConsoleWrite(Json_ObjGetCount($myarray))

Feeling i'm missing something very obvious :)

Edited by trekker

Share this post


Link to post
Share on other sites

solved it:

Local $Obj = Json_Decode($Json1)
$myarray = (Json_Get($Obj, '["aaData"]'))
$i = 0
For $element IN $myarray
   ConsoleWrite(Json_Get($myarray[$i], '["date"]') & @LF)
   ConsoleWrite(Json_Get($myarray[$i], '["status"]') & @LF)
   ConsoleWrite(Json_Get($myarray[$i], '["amount"]') & @LF)
   ConsoleWrite(Json_Get($myarray[$i], '["creditDebitType"]') & @LF)
   ConsoleWrite(Json_Get($myarray[$i], '["sourceDestinationDescriptor"]') & @LF)
   ConsoleWrite(Json_Get($myarray[$i], '["description"]') & @LF)
   $i = $i + 1
next

 

1 person likes this

Share this post


Link to post
Share on other sites

the json.zip is not available to download, where i can get it , thanks a lot

Share this post


Link to post
Share on other sites

#74 ·  Posted (edited)

ill rephrase my question tomorrow

 

/edit

Edited by Mentis

Share this post


Link to post
Share on other sites

Could the latest release be attached to the forum thread?
Some people (like me) may not be allowed to download from Google Drive :(

Share this post


Link to post
Share on other sites
28 minutes ago, argumentum said:

Json(2015.01.08).zip

Thanks @argumentum 

Some countries/companies do not allow access to such services for censorship/security reasons.
https://en.wikipedia.org/wiki/Great_Firewall

- It's not just security. It's defence.

1 person likes this

Share this post


Link to post
Share on other sites

hi guys,

When i add an entry like this, it's the '0000' are truncaded...

Json_Put($Obj, ".00000000465", "foo")

#Include "Json.au3"

ConsoleWrite("resultat:" & test3()  & @crlf )

Func Test3()
    Local $Obj
    Json_Put($Obj, ".00000000465", "foo")
    Json_Put($Obj, ".bar[0]", "bar")
    Json_Put($Obj, ".test[1].foo.bar[2].foo.bar", "Test") ; dot notation

    Local $Json = Json_Encode($Obj,$Json_PRETTY_PRINT)
    ConsoleWrite("Test3 Result: " & $Json & @LF)

;~  Return Json_Get($Obj, '["test"][1]["foo"]["bar"][2]["foo"]["bar"]') = "Test" ; square bracket notation
EndFunc

Result is:

{
    "465": "foo",
    "bar": [
        "bar"
    ],
    "test": [
        "",
        {
            "foo": {
                "bar": [
                    "",
                    "",
                    {
                        "foo": {
                            "bar": "Test"
                        }
                    }
                ]
            }
        }
    ]
}

so i have an existing json in which an object is named '00000000465', an i want to ad an entry, but my command;

Json_Put($Obj, ".00000000465", "foo")

this command only create a new object '465'

Test file added.

Thanks to all

Nicolas.

Json_Test.au3

Share this post


Link to post
Share on other sites

ok i answer to myself,

found this, which seems to mean that dot notation can't be used with number data..

 

Func Json_Put(ByRef $Var, $Notation, $Data, $CheckExists = False)
[...]
    $Index = String(Json_Decode($Match[3])) ; only string using dot notation

So i' got this

{
        "0000000001": {
            "name": "toto",
            "ADR_IP": "192.168.1.1"
        },
        "0000000002": {
            "name": "titi",
            "ADR_IP": "192.168.1.2"
        }
       }

How can i add en entry into 0000000002 ?

thanks

Share this post


Link to post
Share on other sites

#80 ·  Posted (edited)

ok ok... i've found ..

end of the monologue..

thanks.

Json_Put($Obj,'["POPO"]["NUM_CONTRAT"]','valeurtoto')
    Json_Put($Obj,'["POPO"][bplbb][rzrrzr]','valeurtoto')
    Json_Put($Obj,'["POPO"]["0000000045646"][rzrrtttzr]','valeurtoto')
    Json_Put($Obj, ".bar[0]", "bar")
    Json_Put($Obj, ".test[1].foo.bar[2].foo.bar", "Test") ; dot notation

 

EDIT: Use of Quote & double quote important

example:

$akeys = Json_ObjGetKeys($JsoEqpt)
    Json_Get($JsoEqpt, '["' & $akeys[0] & '"]["tagInge"]')        => OK  Key between Double quotes:   '   [   "   '   & $akeys
    Json_Get($JsoEqpt, '["' & $akeys[0] & "']['tagInge']")        => Not OK, key between simple quotes    "   [   '   "   & $akeys

    I must indicate that my keys are Numbers only overwise i think it's ok with string key!

Edited by satanico64
use of double quote
1 person likes this

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?