Json$("VarName"): a simple way to extract strings (and numbers) from JSON files

Started by jj2007, August 01, 2022, 09:26:55 AM

Previous topic - Next topic

jj2007

include \masm32\MasmBasic\MasmBasic.inc
  Init                                 ; v v v download only if the local file is not present
  .if Json$(file:"JsonHolidaysIT.txt", "https://date.nager.at/api/v3/PublicHolidays/2022/IT")
        .While 1
                .Break .if Json$("date")==0
                Print eax, " is "
                wPrint wRec$(Json$("localName"))
                PrintLine At(36) "  ", Json$("name")
        .Endw
  .endif
EndOfCode


JSON file (excerpt):
[{"date":"2022-01-01","localName":"Capodanno","name":"New Year's Day","countryCode":"IT","fixed":true,"global":true,"counties":null,"launchYear":1967,"types":["Public"]},
{"date":"2022-01-06","localName":"Epifania","name":"Epiphany","countryCode":"IT","fixed":true,"global":true,"counties":null,"launchYear":null,"types":["Public"]},
{"date":"2022-04-17","localName":"Pasqua","name":"Easter Sunday","countryCode":"IT","fixed":false,"global":true,"counties":null,"launchYear":null,"types":["Public"]}


Output:
2022-01-01 is Capodanno               New Year's Day
2022-01-06 is Epifania                Epiphany
2022-04-17 is Pasqua                  Easter Sunday
2022-04-18 is Lunedì dell'Angelo      Easter Monday
2022-04-25 is Festa della Liberazion  Liberation Day
2022-05-01 is Festa del Lavoro        International Workers Day
2022-06-02 is Festa della Repubblica  Republic Day
2022-08-15 is Ferragosto o Assunzion  Assumption Day
2022-11-01 is Tutti i santi           All Saints Day
2022-12-08 is Immacolata Concezione   Immaculate Conception
2022-12-25 is Natale                  Christmas Day
2022-12-26 is Santo Stefano           St. Stephen's Day


Attached a full example with three sample files, one of them showing how to extract strings from JSON objects. Extract all files to a folder and run the exe (builds with MB of 1 August 22).

I'd be grateful for other JSON files. There are not many examples on the web, so testing is not so easy :rolleyes:

Biterider

Hi JJ
Good to see you added these feature.  :thumbsup:
There are at least 2 assembler sources on the web that have implemented JSON Read/Write operations: ObjAsm and a very good piece of code by mrfearless called cjsontree (recommended).

Attached some random JSON files (the api projector project has many JSON files describing the APIs).

Biterider

jj2007

Nice samples, thanks :thumbsup:

include \masm32\MasmBasic\MasmBasic.inc
  Init
  .if Json$(file:"TestMe2.json") ; open and load a file
.While 1
.Break .if !Json$("pid") ; get the next record
xchg eax, ecx
PrintLine ecx, " is a ", Json$("main_category"), " with ", Json$("hair_color"), " hair"
.Endw
  .endif
EndOfCode


AbbyThompson is a girl with black hair
KissFromVenus is a girl with blonde hair
ProvenceRose is a girl with blonde hair
EmilyWaller is a girl with black hair
LilySweetyBB is a girl with black hair
AliseSunshine is a hot_flirt with blonde hair
ZairraAsh is a girl with blonde hair

jj2007

Quote from: Biterider on August 01, 2022, 04:20:26 PM(the api projector project has many JSON files describing the APIs)

Very useful link, thanks. Inter alia, there is Data.HtmlHelp.json with lots of constants. Here is a snippet that extracts them:

include \masm32\MasmBasic\MasmBasic.inc
  Init
  .if Json$(file:"win32json-main\api\Data.HtmlHelp.json")
        .While 1
                .Break .if !Json$(Arr:"Constants")      ; search only inside the [Constants array]
                .While 1
                        .Break .if !Json$("Name")
                        Print eax
                        PrintLine At(28) Str$(" %i ", Json$(num:"Value")v)
                .Endw
                Json$(ArrEnd)           ; search full text
        .Endw
  .endif
EndOfCode


HH_DISPLAY_TOPIC             0
HH_HELP_FINDER               0
HH_DISPLAY_TOC               1
HH_DISPLAY_INDEX             2
HH_DISPLAY_SEARCH            3
HH_SET_WIN_TYPE              4
HH_GET_WIN_TYPE              5
HH_GET_WIN_HANDLE            6
HH_ENUM_INFO_TYPE            7
HH_SET_INFO_TYPE             8
HH_SYNC                      9
HH_RESERVED1                 10
HH_RESERVED2                 11
HH_RESERVED3                 12
HH_KEYWORD_LOOKUP            13
HH_DISPLAY_TEXT_POPUP        14
HH_HELP_CONTEXT              15
HH_TP_HELP_CONTEXTMENU       16
HH_TP_HELP_WM_HELP           17
HH_CLOSE_ALL                 18
HH_ALINK_LOOKUP              19
HH_GET_LAST_ERROR            20
HH_ENUM_CATEGORY             21
HH_ENUM_CATEGORY_IT          22
HH_RESET_IT_FILTER           23
HH_SET_INCLUSIVE_FILTER      24
HH_SET_EXCLUSIVE_FILTER      25
HH_INITIALIZE                28
HH_UNINITIALIZE              29
HH_SET_QUERYSERVICE          30
HH_PRETRANSLATEMESSAGE       253
HH_SET_GLOBAL_PROPERTY       252
HH_SAFE_DISPLAY_TOPIC        32
HHWIN_PROP_TAB_AUTOHIDESHOW  1
HHWIN_PROP_ONTOP             2
HHWIN_PROP_NOTITLEBAR        4
HHWIN_PROP_NODEF_STYLES      8
HHWIN_PROP_NODEF_EXSTYLES    16
HHWIN_PROP_TRI_PANE          32
HHWIN_PROP_NOTB_TEXT         64
HHWIN_PROP_POST_QUIT         128
HHWIN_PROP_AUTO_SYNC         256
HHWIN_PROP_TRACKING          512
HHWIN_PROP_TAB_SEARCH        1024
HHWIN_PROP_TAB_HISTORY       2048
HHWIN_PROP_TAB_FAVORITES     4096
HHWIN_PROP_CHANGE_TITLE      8192
HHWIN_PROP_NAV_ONLY_WIN      16384
HHWIN_PROP_NO_TOOLBAR        32768
HHWIN_PROP_MENU              65536
HHWIN_PROP_TAB_ADVSEARCH     131072
HHWIN_PROP_USER_POS          262144
HHWIN_PROP_TAB_CUSTOM1       524288
HHWIN_PROP_TAB_CUSTOM2       1048576
HHWIN_PROP_TAB_CUSTOM3       2097152
HHWIN_PROP_TAB_CUSTOM4       4194304
HHWIN_PROP_TAB_CUSTOM5       8388608
HHWIN_PROP_TAB_CUSTOM6       16777216
HHWIN_PROP_TAB_CUSTOM7       33554432
HHWIN_PROP_TAB_CUSTOM8       67108864
HHWIN_PROP_TAB_CUSTOM9       134217728
HHWIN_TB_MARGIN              268435456
HHWIN_PARAM_PROPERTIES       2
HHWIN_PARAM_STYLES           4
HHWIN_PARAM_EXSTYLES         8
HHWIN_PARAM_RECT             16
HHWIN_PARAM_NAV_WIDTH        32
HHWIN_PARAM_SHOWSTATE        64
HHWIN_PARAM_INFOTYPES        128
HHWIN_PARAM_TB_FLAGS         256
HHWIN_PARAM_EXPANSION        512
HHWIN_PARAM_TABPOS           1024
HHWIN_PARAM_TABORDER         2048
HHWIN_PARAM_HISTORY_COUNT    4096
HHWIN_PARAM_CUR_TAB          8192
HHWIN_BUTTON_EXPAND          2
HHWIN_BUTTON_BACK            4
HHWIN_BUTTON_FORWARD         8
HHWIN_BUTTON_STOP            16
HHWIN_BUTTON_REFRESH         32
HHWIN_BUTTON_HOME            64
HHWIN_BUTTON_BROWSE_FWD      128
HHWIN_BUTTON_BROWSE_BCK      256
HHWIN_BUTTON_NOTES           512
HHWIN_BUTTON_CONTENTS        1024
...
HHWIN_NAVTAB_BOTTOM          2
HH_TAB_CONTENTS              0
HH_TAB_INDEX                 1
HH_TAB_SEARCH                2
HH_TAB_FAVORITES             3
HH_TAB_HISTORY               4
HH_TAB_AUTHOR                5
HH_TAB_CUSTOM_FIRST          11
HH_TAB_CUSTOM_LAST           19
HHACT_TAB_CONTENTS           0
HHACT_TAB_INDEX              1
HHACT_TAB_SEARCH             2
HHACT_TAB_HISTORY            3
HHACT_TAB_FAVORITES          4
HHACT_EXPAND                 5
HHACT_CONTRACT               6
HHACT_BACK                   7
HHACT_FORWARD                8
HHACT_STOP                   9
HHACT_REFRESH                10
HHACT_HOME                   11
HHACT_SYNC                   12
HHACT_OPTIONS                13
HHACT_PRINT                  14
HHACT_HIGHLIGHT              15
HHACT_CUSTOMIZE              16
HHACT_JUMP1                  17
HHACT_JUMP2                  18
HHACT_ZOOM                   19
HHACT_TOC_NEXT               20
HHACT_TOC_PREV               21
HHACT_NOTES                  22
HHACT_LAST_ENUM              23


How would equivalent code look like in ObjAsm?

HSE

Equations in Assembly: SmplMath

jj2007

Quote from: HSE on August 02, 2022, 05:45:54 AM
Quote from: jj2007 on August 02, 2022, 04:41:26 AM
How would equivalent code look like in ObjAsm?

Fantastic  :biggrin:, you can do that  :thumbsup:

I had hoped that you could demonstrate that, Hector - you are the expert for ObjAsm :thumbsup:

HSE

Quote from: jj2007 on August 02, 2022, 08:11:37 AM
I had hoped that you could demonstrate that

I learned about JSON with Fearless program, and I maked a translation of a couple of database from CSV to JSON with ObjAsm. But now I'm using Java, because almost same routines work in Android applications that run in my phone (Java JSON libraries in PC and phone are not exactly the same).

You have to begin with Demo01A :
1 - create an object with New
2 - Init the object
3 - Call methods, and watch debug messages in DebugCenter
4 - Destroy the object

If you can see how that work, you can jump directly to what you want.

:biggrin: Just in case, critical part (see JSONDemo_Main.inc ):  New DskStream::DiskStream
  OCall DskStream::DiskStream.Init, xsi, $OfsCStr("Data.json"), GENERIC_READ or GENERIC_WRITE, \
                                    0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
  mov xbx, $New(Json)
  OCall xbx::Json.Init, xsi
  OCall xbx::Json.Read, addr DskStream


later: I have a keyboard problem with "f"  :biggrin:

Equations in Assembly: SmplMath

Biterider

Hi
Thanks HSE for the quick response  :thumbsup:

The code looks like (works for 32 and 64 bit, ANSI and WIDE strings)

  New DskStream::DiskStream
  OCall DskStream::DiskStream.Init, xsi, $OfsCStr("Data.HtmlHelp.json"), GENERIC_READ or GENERIC_WRITE, \
                                    0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
  mov xbx, $New(Json)
  OCall xbx::Json.Init, xsi
  OCall xbx::Json.Read, addr DskStream

  mov pConstants, $OCall(xbx::Json.GetProperty, addr [xbx].$Obj(Json).RootProperty, $OfsCStr("Constants"))

  mov dIndex, 0
  .while TRUE
    mov pConstant, $OCall(xbx::Json.GetArrayItem, pConstants, dIndex)
    .break .if pConstant == NULL
    OCall xbx::Json.GetProperty, pConstant, $OfsCStr("Name")
    m2m pName, [xax].JSON_PROPERTY.pValue, xdx
    OCall xbx::Json.GetProperty, pConstant, $OfsCStr("Value")
    m2m pValue, [xax].JSON_PROPERTY.pValue, xdx
    lea xdi, wBuffer
    PrintF xdi, "¦ST¦AT¦ST", pName, 35, pValue
    invoke DbgOutText, xdi, DBG_COLOR_TEXT, DBG_EFFECT_NEWLINE, $OfsCStr("HtmlHelp Constants")
    inc dIndex
  .endw

  Destroy xbx
  OCall DskStream::DiskStream.Done


The output (attached) is:

HH_DISPLAY_TOPIC                   0
HH_HELP_FINDER                     0
HH_DISPLAY_TOC                     1
HH_DISPLAY_INDEX                   2
HH_DISPLAY_SEARCH                  3
HH_SET_WIN_TYPE                    4
HH_GET_WIN_TYPE                    5
HH_GET_WIN_HANDLE                  6
HH_ENUM_INFO_TYPE                  7
HH_SET_INFO_TYPE                   8
HH_SYNC                            9
HH_RESERVED1                       10
HH_RESERVED2                       11
HH_RESERVED3                       12
...


Biterider

jj2007

Thanks, Biterider :thup:

The approach looks pretty similar, but of course, my version looks more "Basic" ;-)

Quote from: Biterider on August 02, 2022, 04:59:06 PM
The code looks like (works for 32 and 64 bit, ANSI and WIDE strings)

  New DskStream::DiskStream
  OCall DskStream::DiskStream.Init, xsi, $OfsCStr("Data.HtmlHelp.json"), GENERIC_READ or GENERIC_WRITE, \
                                    0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
  mov xbx, $New(Json)
  OCall xbx::Json.Init, xsi
  OCall xbx::Json.Read, addr DskStream

  mov pConstants, $OCall(xbx::Json.GetProperty, addr [xbx].$Obj(Json).RootProperty, $OfsCStr("Constants"))

  mov dIndex, 0
  .while TRUE
    mov pConstant, $OCall(xbx::Json.GetArrayItem, pConstants, dIndex)
    .break .if pConstant == NULL
    OCall xbx::Json.GetProperty, pConstant, $OfsCStr("Name")
    m2m pName, [xax].JSON_PROPERTY.pValue, xdx
    OCall xbx::Json.GetProperty, pConstant, $OfsCStr("Value")
    m2m pValue, [xax].JSON_PROPERTY.pValue, xdx
    lea xdi, wBuffer
    PrintF xdi, "¦ST¦AT¦ST", pName, 35, pValue
    invoke DbgOutText, xdi, DBG_COLOR_TEXT, DBG_EFFECT_NEWLINE, $OfsCStr("HtmlHelp Constants")
    inc dIndex
  .endw

  Destroy xbx
  OCall DskStream::DiskStream.Done

include \masm32\MasmBasic\MasmBasic.inc
  Init
  .if Json$(file:"win32json-main\api\Data.HtmlHelp.json")
.While 1
.Break .if !Json$(Arr:"Constants") ; search only inside [Constants arrays]
.While 1
.Break .if !Json$("Name") ; exit if no more "Name" found in this array
Print eax
PrintLine At(28) Str$(" %i ", Json$(num:"Value")v)
.Endw
Json$(ArrEnd) ; back to full text search, find the next [Constants array]
.Endw
  .endif
EndOfCode


Note:
With Json$(ucfile:"somefile.txt"), you can load Unicode files, too.
With Json$(Arr:"somekey") ... Json$(ArrEnd), search is limited to [arrays]
With Json$(Obj:"somekey") ... Json$(ObjEnd), search is limited to {objects}

HSE

Hi JJ!

Quote from: jj2007 on August 02, 2022, 09:51:01 PM
The approach looks pretty similar

Not even close I think.

Quote from: jj2007 on August 02, 2022, 09:51:01 PM
With Json$(Arr:"somekey") ... Json$(ArrEnd), search is limited to [arrays]
With Json$(Obj:"somekey") ... Json$(ObjEnd), search is limited to {objects}

That can be misleading.

A JSON file it's not a text, it's an streamed complex polymorphic object (obviously at first was a JavaScript Object). Only one object.

The loader can read any object structure in memory (if well formed), and you don't see anymore a text. Beyond that, you must know exactly what object was streamed in the JSON file.

HSE

Equations in Assembly: SmplMath

jj2007

Hi Hector,

Json has {objects} and [arrays] (see SOF). Conceptionally, that's a big difference, but from a parsing point of view the difference is marginal.

I'm not a philosopher; I want to programmatically extract strings or numbers from a Json file. So either I open that file in Notepad and check the structure; or I use a Json viewer like MiTeC to examine the structure, and then write a simple proggie.

I'm still working on it. It's not that easy to find something simple and foolproof ;-)

HSE

Hi JJ!

:biggrin: It's not easy.   :thumbsup:

Quote from: jj2007 on August 03, 2022, 02:26:57 AM
Json has {objects} and [arrays]

Not really. There are only objects. [array] is just an object that store address of first object in a LinkedList.

You can program JSONObject and JSONArray like different related objects, or exactly the same object. You can see Biterider maked only one object, and JSON_PROPERTY is the only thing that build all the squeleton. Perched to objects can be Strings allocated in memory.

Quote from: jj2007 on August 03, 2022, 02:26:57 AM
I'm not a philosopher

Ahh, sorry  :azn:

Quote from: jj2007 on August 03, 2022, 02:26:57 AM
I want to programmatically extract strings or numbers from a Json file

You can do that easily, but you only can guess what that strings or numbers means (not big problem in very elemental JSON files designed to be humans readed :biggrin:).

Nothing in a JSON file is forced to say what things represent, there is not rules about names, and there is no rules about linking order. All the rules and processes are in the controller of the object streamed to the file. Naturally, I have no problem to read my JSON files, because I maked the rules.

Simplicity is not mandatory, and a program that make guesses about string or number meanings is not reliable.

Quote from: jj2007 on August 03, 2022, 02:26:57 AM
So either I open that file in Notepad...

For edition in plain text nothing beat qEditor. In parsed text, Visual Studio is fantastic (you write like plain text but editor is following structure and warning about missing delimiters, etc.). And to see and edit structure Fearless' cJSONTree is very usefull.

HSE
Equations in Assembly: SmplMath

jj2007

Quote from: HSE on August 03, 2022, 04:39:27 AM
Quote from: jj2007 on August 03, 2022, 02:26:57 AM
I want to programmatically extract strings or numbers from a Json file

You can do that easily, but you only can guess what that strings or numbers means (not big problem in very elemental JSON files designed to be humans readed :biggrin:).
...
For edition in plain text nothing beat qEditor. In parsed text, Visual Studio is fantastic (you write like plain text but editor is following structure and warning about missing delimiters, etc.). And to see and edit structure Fearless' cJSONTree is very useful.

Hi Hector,

We could argue for ages, but as a matter of fact neither the MiTeC viewer nor fearless' cJSONTree allow to extract strings from a json file. Fearless' tool is excellent btw, I'll drop the MiTeC stuff.

As to editors, that's a personal choice, as usual :tongue: