Jump to content

A Non-Strict JSON UDF (JSMN)


Ward
 Share

Recommended Posts

I think I need another tip.  How about this. How would I get the count of groups in this example:

{   
    "groups": [{
       "id": "11",
       "name": "ItemA"
       },{
       "id": "22",
       "name": "ItemB"
       },{
       "id": "33",
       "name": "ItemC"
    }]
}

This isn't working:

Local $oJson = Json_Decode($Json1)
Local $aoItems = Json_Get($oJson, ".")
ConsoleWrite($aoItems.Count)

 

Edited by NassauSky
Link to comment
Share on other sites

$ojson   = Json_Decode($JSON)
$aGroups = Json_Get($ojson, ".groups")
ConsoleWrite("Groups count = " & UBound($aGroups) & @CRLF)

.groups is an array of json objects.  So you would get the count of how many array items like you would with any other array.

Edited by TheXman
Link to comment
Share on other sites

Correct, the value of .groups is an array, not a JSON object.

You're welcome. :)

Edited by TheXman
Link to comment
Share on other sites

  • 1 month later...

Just to inform you about our research results, this library can cause a memory access violation error message that keeps windows from shutting down (stop shutdown and asking the user to hit OK).

Error msg: "The Instruction at 0x%address% referenced memory at 0x%same_address%. The memory could not be written. Click OK to terminate the program.

 
This happened only on certain Win10 machines and even there it was not always reproduceable, happening only e.g. 3 of 5 times.

So again, the error only occured when we used the library in the time window when windows is doing the shutdown, e.g. 
 

OnAutoItExitRegister("__exit_procedure") 

While 1
    Sleep(500)
WEnd

Func __exit_procedure()
    Json_Encode($object)
EndFunc
 

Run this program and then shutdown windows. 

screenshot here http://www.ffastrans.com/frm/forum/viewtopic.php?f=4&t=1184#p6154

 

Edited by emcodem
Link to comment
Share on other sites

Thanks for the tipp @Danp2 ..if i am right, the workaround you applied was the same than we did: just don't execute the affected function in the OnAutoItExitRegister callback but somewhen else and grab the json encoded stuff from a global variable instead.

For example we worked around by just using regex on the already encoded json. But a workaround is not a fix and i fear we are not the only ones that suffer from such an issue and spend huge amounts of time to debug it. Thats why i thought its good to post this here.

What i can add additionally, it don't seem to be directly connected to OnAutoItExitRegister. We had the same behaviour in an older version of our program when detecting the program shutdown in our own code and were executing Json_Encode inside an AdlibRegister Function. Using this method, the Adlib function ran thousands of time at runtime without any problem but as it was executed in this time spot when windows shuts down, Json_encode caused the mentioned issue.

Unfortunately, below is not tested but this was about how our old program version worked hehe...

AdlibRegister("_ProcAdmin", 1000)
Func _ProcAdmin()
    ...lots of code
    Json_Encode($object)
    ...lots of code
EndFunc 

 

Edited by emcodem
Link to comment
Share on other sites

{
    "type": "success",
    "code": "s-portfolio-0001",
    "description": "Success position",
    "result": {
        "positionList": [
            {
                "AccountID": "ASIA",
                "TradingSymbol": "BANKNIFTY 04FEB2021 CE 34700",
                "ExchangeSegment": "NSEFO",
                "ExchangeInstrumentId": "38544",
                "ProductType": "NRML",
                "Marketlot": "25",
                "Multiplier": "1",
                "BuyAveragePrice": "0.00",
                "SellAveragePrice": "394.89",
                "OpenBuyQuantity": "0",
                "OpenSellQuantity": "200",
                "Quantity": "-200",
                "BuyAmount": "0.00",
                "SellAmount": "78,977.50",
                "NetAmount": "78,977.50",
                "UnrealizedMTM": "34,447.50",
                "RealizedMTM": "0.00",
                "MTM": "34,447.50",
                "BEP": "394.89",
                "SumOfTradedQuantityAndPriceBuy": "0.00",
                "SumOfTradedQuantityAndPriceSell": "78,977.50",
                "MessageCode": 9002,
                "MessageVersion": 1,
                "TokenID": 0,
                "ApplicationType": 0,
                "SequenceNumber": 344181107247201
            },
            {
                "AccountID": "ASIA",
                "TradingSymbol": "BANKNIFTY 04FEB2021 PE 34100",
                "ExchangeSegment": "NSEFO",
                "ExchangeInstrumentId": "46488",
                "ProductType": "NRML",
                "Marketlot": "25",
                "Multiplier": "1",
                "BuyAveragePrice": "0.00",
                "SellAveragePrice": "401.79",
                "OpenBuyQuantity": "0",
                "OpenSellQuantity": "200",
                "Quantity": "-200",
                "BuyAmount": "0.00",
                "SellAmount": "80,358.75",
                "NetAmount": "80,358.75",
                "UnrealizedMTM": "-15,441.25",
                "RealizedMTM": "0.00",
                "MTM": "-15,441.25",
                "BEP": "401.79",
                "SumOfTradedQuantityAndPriceBuy": "0.00",
                "SumOfTradedQuantityAndPriceSell": "80,358.75",
                "MessageCode": 9002,
                "MessageVersion": 1,
                "TokenID": 0,
                "ApplicationType": 0,
                "SequenceNumber": 344181107247202
            },
            {
                "AccountID": "ASIA",
                "TradingSymbol": "BANKNIFTY 04FEB2021 PE 34000",
                "ExchangeSegment": "NSEFO",
                "ExchangeInstrumentId": "46486",
                "ProductType": "NRML",
                "Marketlot": "25",
                "Multiplier": "1",
                "BuyAveragePrice": "0.00",
                "SellAveragePrice": "356.82",
                "OpenBuyQuantity": "0",
                "OpenSellQuantity": "250",
                "Quantity": "-250",
                "BuyAmount": "0.00",
                "SellAmount": "89,203.75",
                "NetAmount": "89,203.75",
                "UnrealizedMTM": "-17,796.25",
                "RealizedMTM": "0.00",
                "MTM": "-17,796.25",
                "BEP": "356.82",
                "SumOfTradedQuantityAndPriceBuy": "0.00",
                "SumOfTradedQuantityAndPriceSell": "89,203.75",
                "MessageCode": 9002,
                "MessageVersion": 1,
                "TokenID": 0,
                "ApplicationType": 0,
                "SequenceNumber": 344181107247203
            },
            {
                "AccountID": "ASIA",
                "TradingSymbol": "BANKNIFTY 04FEB2021 PE 33900",
                "ExchangeSegment": "NSEFO",
                "ExchangeInstrumentId": "36195",
                "ProductType": "NRML",
                "Marketlot": "25",
                "Multiplier": "1",
                "BuyAveragePrice": "0.00",
                "SellAveragePrice": "315.74",
                "OpenBuyQuantity": "0",
                "OpenSellQuantity": "200",
                "Quantity": "-200",
                "BuyAmount": "0.00",
                "SellAmount": "63,147.50",
                "NetAmount": "63,147.50",
                "UnrealizedMTM": "-13,112.50",
                "RealizedMTM": "0.00",
                "MTM": "-13,112.50",
                "BEP": "315.74",
                "SumOfTradedQuantityAndPriceBuy": "0.00",
                "SumOfTradedQuantityAndPriceSell": "63,147.50",
                "MessageCode": 9002,
                "MessageVersion": 1,
                "TokenID": 0,
                "ApplicationType": 0,
                "SequenceNumber": 344181107247204
            },
            {
                "AccountID": "ASIA",
                "TradingSymbol": "BANKNIFTY 04FEB2021 CE 34600",
                "ExchangeSegment": "NSEFO",
                "ExchangeInstrumentId": "38540",
                "ProductType": "NRML",
                "Marketlot": "25",
                "Multiplier": "1",
                "BuyAveragePrice": "0.00",
                "SellAveragePrice": "430.22",
                "OpenBuyQuantity": "0",
                "OpenSellQuantity": "200",
                "Quantity": "-200",
                "BuyAmount": "0.00",
                "SellAmount": "86,043.75",
                "NetAmount": "86,043.75",
                "UnrealizedMTM": "36,433.75",
                "RealizedMTM": "0.00",
                "MTM": "36,433.75",
                "BEP": "430.22",
                "SumOfTradedQuantityAndPriceBuy": "0.00",
                "SumOfTradedQuantityAndPriceSell": "86,043.75",
                "MessageCode": 9002,
                "MessageVersion": 1,
                "TokenID": 0,
                "ApplicationType": 0,
                "SequenceNumber": 344181107247205
            },
            {
                "AccountID": "ASIA",
                "TradingSymbol": "BANKNIFTY 04FEB2021 CE 34500",
                "ExchangeSegment": "NSEFO",
                "ExchangeInstrumentId": "38537",
                "ProductType": "NRML",
                "Marketlot": "25",
                "Multiplier": "1",
                "BuyAveragePrice": "0.00",
                "SellAveragePrice": "469.17",
                "OpenBuyQuantity": "0",
                "OpenSellQuantity": "200",
                "Quantity": "-200",
                "BuyAmount": "0.00",
                "SellAmount": "93,833.75",
                "NetAmount": "93,833.75",
                "UnrealizedMTM": "38,503.75",
                "RealizedMTM": "0.00",
                "MTM": "38,503.75",
                "BEP": "469.17",
                "SumOfTradedQuantityAndPriceBuy": "0.00",
                "SumOfTradedQuantityAndPriceSell": "93,833.75",
                "MessageCode": 9002,
                "MessageVersion": 1,
                "TokenID": 0,
                "ApplicationType": 0,
                "SequenceNumber": 344181107247206
            }
        ]
    }
}

 

 

How can I get result.PositionList into a 2D array.
 

$jsontemp = Json_Decode($oReceived)
    $positionlist = Json_ObjGet($jsontemp, "result.positionList")


 

 

Link to comment
Share on other sites

On 2/2/2021 at 1:17 AM, adityaparakh said:

How can I get result.PositionList into a 2D array.
 

$jsontemp = Json_Decode($oReceived)
$positionlist = Json_ObjGet($jsontemp, "result.positionList")

 

@adityaparakh

Since you provided absolutely no information related to what your 2D array should look like or contain, the well-documented example below is very generic.  With 100's of relevant examples across the forums (including many in this topic alone), one would think you could have shown a little more effort than the two lines that you provided. <_<

#include <Constants.au3>
#include <Array.au3>
#include "json.au3" ; <== Modify as needed

Const $JSON_DATA = _
          '{' & _
          '   "type": "success",' & _
          '   "code": "123ABC",' & _
          '   "description": "Another simple example",' & _
          '   "result": {' & _
          '      "fruits": [' & _
          '         {"Fruit": "Apple"     , "Qty": 34700, "Cost": 94.89, "Status": false},' & _
          '         {"Fruit": "Banana"    , "Qty": 34100, "Cost": 01.79, "Status": true} ,' & _
          '         {"Fruit": "Orange"    , "Qty": 34000, "Cost": 56.82, "Status": true} ,' & _
          '         {"Fruit": "Mango"     , "Qty": 33900, "Cost": 15.74, "Status": false},' & _
          '         {"Fruit": "Pineapple" , "Qty": 34600, "Cost": 30.22, "Status": false},' & _
          '         {"Fruit": "Cantaloupe", "Qty": 34500, "Cost": 69.17, "Status": false}'  & _
          '      ]' & _
          '   }' & _
          '}'

json_udf_example()

Func json_udf_example()
    Local $oJson
    Local $aResult[0][3]

    ;Decode JSON to an object
    $oJson  = Json_Decode($JSON_DATA)
    If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "Unable to decode JSON - @error = " & @error)

    ;For each object in the array
    For $oFruit in json_get($oJson, ".result.fruits")
        ;Add a row of data to the table
        _ArrayAdd($aResult, _
            Json_Get($oFruit, ".Fruit") & "|" & _
            Json_Get($oFruit, ".Qty")   & "|" & _
            Json_Get($oFruit, ".Cost") _
        )
        If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "_ArrayAdd failed - @error = " & @error)
    Next

    ;Display result
    _ArrayDisplay($aResult, "Example 2D Array", "", 0, Default, "Fruit|Qty|Cost")
EndFunc

image.png.2db70d42fd1f3923eac3e03640febf19.png

Edited by TheXman
Made script more generic
Link to comment
Share on other sites

Was the source code for the embedded binary/machine code ever released? I am interested in the encoding function as jsmn doesn't provide such a thing.

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

3 hours ago, TheDcoder said:

I am interested in the encoding function as jsmn doesn't provide such a thing.

If you aren't able to find the original source, then at the bottom of this page there are numerous links to github JSON implementations in several different languages.  Or, you can always write your own JSON string encoding routine using RFC 7159 as your reference.

Edited by TheXman
Link to comment
Share on other sites

@TheXman Thank you for the links, I am aware of them. I did some research but I realized that I don't really need to depend on jsmn... :)

P.S For anyone who is interested in what I am trying to do, I am basically trying to dump some structs from C into a readable format for debugging purposes, this is for the "EasyCodeIt" project I am working on, see my signature.

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

  • 1 month later...
#include "JSON.au3"
Json_Test()


Func Json_Test()
    Local $sJSON = '[{"name":"Jon", "surname":"Snow"}{"name":"Daenerys","surname":"Targaryen"}]'
    Json_Dump($sJSON)
    Local $oJSON = Json_Decode($sJSON)
    Json_ObjDelete($oJSON, "[0]")
    Local $sJSON2 = Json_Encode($oJSON)
    Json_Dump($sJSON2)
EndFunc

Can someone help me to delete entry

{"name":"Jon", "surname":"Snow"}

?

Link to comment
Share on other sites

  • Developers

I think the jason string is invalid and missing a comma :

Local $sJSON = '[{"name":"Jon", "surname":"Snow"},{"name":"Daenerys","surname":"Targaryen"}]'

.. but also believe the UDF has trouble lexing it as it returns an Array in stead of an Object.

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

4 minutes ago, Jos said:

.. but also believe the UDF has trouble lexing it as it returns an Array in stead of an Object.

The JSON data in your post is indeed an array with two objects inside it.

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

  • Developers

mmm that indeed makes sense so one needs to delete the array entry 0 in this case  or just use array entry 1 works too in this example

#include "JSON.au3"
Json_Test()

Func Json_Test()
    Local $sJSON = '[{"name":"Jon", "surname":"Snow"},{"name":"Daenerys","surname":"Targaryen"},]'
    Json_Dump($sJSON)
    Local $oJSON = Json_Decode($sJSON)
    ConsoleWrite(Json_encode($oJSON[1]) & @crlf)
EndFunc

 

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

If you want to programmatically search the array for the object(s) of interest, instead of hard-coding it, you could do something like:

#include <Constants.au3>
#include <Array.au3>
#Include <json.au3>

Const $JSON_DATA = '[{"name":"Jon","surname":"Snow"},{"name":"Daenerys","surname":"Targaryen"}]'

delete_json_array_items_example()

Func delete_json_array_items_example()
    Local $oJson
    Local $aoJson[0]

    ;Decode JSON
    $aoJson = Json_Decode($JSON_DATA)
    If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "Unable to parse JSON - @error = " & @error)

    ConsoleWrite("Before:" & @CRLF & Json_Encode($aoJson, $JSON_PRETTY_PRINT) & @CRLF)

    ;For each JSON array item
    For $i = UBound($aoJson) - 1 To 0 Step -1
        ;Get object. If it's an object of interest, then remove it from the array
        $oJson = json_get($aoJson, "[" & $i & "]")
        If Json_Get($oJson, ".name") = "Jon" And Json_Get($oJson, ".surname") = "Snow" Then _ArrayDelete($aoJson, $i)
    Next

    ConsoleWrite(@CRLF & "After:" & @CRLF & Json_Encode($aoJson, $JSON_PRETTY_PRINT) & @CRLF)
EndFunc

Console:

Before:
[
    {
        "name": "Jon",
        "surname": "Snow"
    },
    {
        "name": "Daenerys",
        "surname": "Targaryen"
    }
]

After:
[
    {
        "name": "Daenerys",
        "surname": "Targaryen"
    }
]

 

Edited by TheXman
Link to comment
Share on other sites

  • Developers

.. I do however think there should be some sort of support for deleting array entries in the UDF and we probably could even include it in the objdelete() UDF by testing whether the supplied variable is an Obj or Array....agree? ... so basically combining the existing with your logic.

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

If that question was directed towards me:

Although I would rarely disagree that additional, relevant, functionality is a good thing, adding functionality to a UDF library when that functionality already exists seems a bit unnecessary and duplicative.  JSON arrays are still just arrays.  There's already a very effective UDF that deletes array entries, _ArrayDelete().  What would be the benefit of the json.au3 file having its own  function that basically does the same thing?  Furthermore, how would you implement it in this case where it may have multiple criteria for the selection of an item that needs to be deleted? I mean I know it can be done, but is it really worth the effort when there is already a whole UDF library dedicated to array maintenance and manipulation?

This was just my off-the-cuff opinion.  If I have misunderstood the direction or tenor of your question, please forgive me. 

Edited by TheXman
Link to comment
Share on other sites

  • Developers

It was just a generic question to all but do appreciate your thoughts. :) 
Looking at the functions we do already have these commands for an Arrray:

  • Json_get()
  • Json_put()

So thought it would be nice to add Json_del() to that list as well. 
Another thought was to add a check at the beginning of eg the Json_*get() functions to check for IsObj() and isArray() and use the "other"function when it is the wrong type of input..... just to make things much easier to use it.   ( just thinking out loud here :) ) 

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

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