Jump to content

A Non-Strict JSON UDF (JSMN)


Ward
 Share

Recommended Posts

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

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

  • 2 weeks later...

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.

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

 

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

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

  • 1 month later...

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"}].

 

Link to comment
Share on other sites

  • 1 month later...

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

 

Link to comment
Share on other sites

  • 3 weeks later...
  • 6 months later...

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

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

Link to comment
Share on other sites

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