Skip to content
⌘ NSIS Forum Archive

nsJSON plug-in

82 posts

Anders#
JSON does not really have comments AFAIK.

The safest option is to use _mycomment:"comment text" style entries.

If you still want a real comment then /**/ block comments probably have a higher chance of working across parsers...
Marshallx7#
This plugin is awesome.

However, is there any chance of adding an escape function to convert an NSIS string into a JSON string?

For example, right now if I call
nsjson::Set some node path /value ":"
Then the colon is not stored because it is invalid JSON, not a string. I have to call
nsjson::Set some node path /value `":"`

But if I don't know where the text has come from e.g.
nsjson::Set some node path /value $R0
Then that's a problem.

One of the following would be ideal:
nsjson::escape $R0
Pop $R0
nsjson::Set some node path /value $R0

alternatively,
nsjson::Set some node path /value /escape $R0

Such a function shouldn't try to determine the type of data - just treat the input as an unescaped, unquoted string.
JasonFriday13#
Try quotes or double quotes around the variable? Like: "$R0". If strings have spaces, they can resolve to multiple arguments when used with a plugin, which is why quotes are needed.
Afrow UK#
1.1.0.1 - 23rd November 2015
* Added Quote function.
* Added amd64-unicode build.

1.1.0.0 - 19th April 2015
* Support for multiple JSON trees.
* JSON via HTTP web requests.
Somehow I hadn't uploaded the last version I'd been working on so I apologise for that. It includes built-in support for multiple JSON trees and HTTP web requests (e.g. for REST APIs).



Stu
Marshallx7#
NB: When you use nsJSON::Get /type, if the nodepath doesn't exist then nothing gets pushed onto the stack - so always make sure you check that the nodepath /exists before you try to get the type.

Stu, you could change /type to return empty string if the node path doesn't exist, and do away with /exists altogether.
Marshallx7#
Hey, Stu
The new Quote function doesn't escape strings whose first and last characters are already quotemarks. For example, nsjson::Quote `"some"text"`
Afrow UK#
Originally Posted by Marshallx7 View Post
Hey, Stu
The new Quote function doesn't escape strings whose first and last characters are already quotemarks. For example, nsjson::Quote `"some"text"`
The output is:
"some\"text"
This is correct assuming the original feature request was to only surround the string in quotes if it isn't so already. Nevertheless:
1.1.0.2 - 9th December 2015
* Get function /type switch returns an empty string if the node does not exist.
* Added /always switch to Quote function which surrounds the input string in quotes even if it is already quoted.
Therefore, use the /always switch and the output will instead be:
"\"some\"text\""
http://nsis.sourceforge.net/File:NsJSON.zip

Stu
Marshallx7#
This is really great Stu, thanks.

Readme needs updating with latest switches behavior btw.

I have another feature request if you feel inclined:

{ a: 'a', b: 1, c: {}}
nsJSON::Get /keys ...
Returns on the stack:
3
a
b
c
Yathosho#
Originally Posted by Marshallx7 View Post
{ a: 'a', b: 1, c: {}}
Erm, I would expect the plugin to deny this input, since it's invalid JSON
Marshallx7#
That was just an example of the JSON object in memory (as valid Javascript rather than JSON), not the string passed to nsJSON to build it. The point was the /keys feature request.
Marshallx7#
I have also found another case where nsJSON::Get does not return anything on the stack:
If you try to get something that doesn't exist (e.g. the specified /tree does not exist)

Please can this be changed to return empty string, to avoid stack corruption?

And I think that nsJSON:😁elete causes NSIS to crash if you try to delete something that doesn't exist.
Afrow UK#
The plug-in will set the error flag if the tree or node does not exist. If you think it is possible the tree or node may not exist, you should check the error flag before reading from the stack. Remember to clear the error flag first if necessary. The error flag is the only way to distinguish a definite error.

I have implemented /keys and fixed the Delete crash but I am working on a new feature for console application execution for JSON input/output so will upload a new version when done.

Stu
Marshallx7#
Just discovered another crash, not sure if this is related to the previous crash in Delete:

nsJSON::Set /tree testTree testNode /value testValue
nsJSON::Get /tree testTree /exists /end
Pop $R0
MessageBox MB_OK $R0 ; "yes"
nsJSON:😁elete /tree testTree /end ; CRASH
Marshallx7#
I'm also having trouble using the unicode version of the plugin:

OutFile "test.exe"
!define SETTING_UNICODE
!ifdef SETTING_UNICODE
Unicode true
!addplugindir /x86-unicode "./plugins/x86-unicode"
!else
Unicode false
!addplugindir /x86-ansi "./plugins/x86-ansi"
!endif
Page instfiles
Function .onInit
nsjson::set /tree testTree testNode /value testValue
nsjson::get /tree testTree testNode /end
Pop $R0
MessageBox MB_OK $R0 ; "testValue"
FunctionEnd
Section "dummy"
SectionEnd
With the ansi version, the message box reads "testValue" as expected, but with the unicode version is just says "t".
JasonFriday13#
Originally Posted by Marshallx7 View Post
I'm also having trouble using the unicode version of the plugin:

OutFile "test.exe"
!define SETTING_UNICODE
!ifdef SETTING_UNICODE
Unicode true
!addplugindir /x86-unicode "./plugins/x86-unicode"
!else
Unicode false
!addplugindir /x86-ansi "./plugins/x86-ansi"
!endif
Page instfiles
Function .onInit
nsjson::set /tree testTree testNode /value testValue
nsjson::get /tree testTree testNode /end
Pop $R0
MessageBox MB_OK $R0 ; "testValue"
FunctionEnd
Section "dummy"
SectionEnd
With the ansi version, the message box reads "testValue" as expected, but with the unicode version is just says "t".
Sounds like you are using the ansi version for both ansi and unicode installers.

By the way, if the plugins are copied correctly to both '${NSISDIR}\plugins\x86-ansi' and '${NSISDIR}\plugins\x86-unicode', then you don't need to use !addplugindir. 'Unicode True' does that work for you.
Marshallx7#
Nope, confirmed I am using the correct builds. DLLs are stored in local plugins directory, not in NSISDIR, hence the use of addplugindir. Does this work for you?
Anders#
When something in a ANSI installer is unexpectedly a single character then it is a clear indication that something was not converted from Unicode to ANSI. The other way around could be anything, a plugin mismatch or bug. A missing conversion bug to Unicode usually looks Chinese.
Afrow UK#
1.1.0.3 - 4th March 2016
* Fixed crash for the Delete function when specifying a tree/path that
does not exist.
* Fixed Unicode build.
* Added /keys switch to Get function.
http://nsis.sf.net/File:NsJSON.zip

I am still working on the process exec code.

Stu
Marshallx7#
Yep, Unicode works fine now, thanks Stu.

I have another feature request:
It would be great if /index accepted negative numbers to get/set/delete from the end of an array/node.
For example, /index -1 means the last element, /index -2 means the second-last element and so on.

Right now, this is achieved by getting the count of elements, decrementing, then getting/setting/deleting the required element. A negative index would streamline this process.
Afrow UK#
1.1.0.5 - 10th August 2016
* Empty value keys ("") were not included in serialized JSON.
* Serialize function popped one extra value from the stack.

1.1.0.4 - 7th June 2016
* Fixed incorrect flags used for HTTP requests.
* Added support for negative indices.
* Added console application execution for input and output.
* Added support for asynchronous HTTP requests and console application
execution.


Stu
awall#
Output NodePath not cleared when response is empty?

Hi Stu,
started using nsJSON recently, very nice work!

I'm facing an issue using HTTP web requests:
nsJSON::Set /tree Request /value `{ "Url": "${myURI}", "Verb": "POST", "DataType": "JSON" }
nsJSON::Set /tree Response /http Request
The REST method I'm calling in the "Url" may have an empty response (e.g. only returns 200 OK).
In such case, the returned Response tree has the "Output" node populated with the response from the previous call to another REST method, instead of returning an empty "Output" node.

Is this a bug or am I missing something?

Thanks
Andrea
Afrow UK#
I have uploaded a new version which fixes the issue.



Stu
Marshallx7#edited
I'm having a problem with the latest build where nsJSON::Serialize is leaving the filepath on the stack. I know there was an issue fixed recently where one too many values were popped but now the reverse seems to be true...

I suspect that the old code was always popping file, even if it wasn't needed, whereas the new code pushes it back on the stack even if it was needed

On a separate note, I have found that doing an http request with Verb=POST and DataType=JSON sends a request where the post data is unicode with Content-Type: application/x-www-form-urlencoded
Is there a way to get this to send as UTF-8 with Content-Type: application/json ?

Thanks
Anders#
How are you supposed to delete a tree? Especially the "default"? tree?

nsJSON::Set /value '{ "Input": [ { "test1": false, } ] }'
nsJSON:😁elete /end # <-- Crash on exit!
nsJSON::Set /value '{ "Input": [ { "test1": false, } ] }'
nsJSON:😁elete "" /end # <-- Does nothing
nsJSON::Set /value '{ "Input": [ { "test1": false, } ] }'
nsJSON::Set /value '{}' # <-- "Works"

nsJSON::Set /value '[]'
nsJSON::Set /value '{ "Input": [ { "test1": false, } ]' # Not valid JSON now?
nsJSON::Set /value '{}' # <-- Now it fails
nsJSON:😁elete /tree "" /end # <-- Crash
Afrow UK#
Originally Posted by Anders View Post
How are you supposed to delete a tree? Especially the "default"? tree?
1.1.1.0 - 21st November 2017
* Fixed JSON with syntax errors still being parsed without setting the error flag.
* Fixed Set function not replacing the root value if the value was an array.
* Fixed Delete function not deleting the root node and tree.


Anders, please let me know if this resolves all your issues. Apologies for the wait.

This will delete the root node and tree:
nsJSON:😁elete /end
Stu
Marshallx7#
I'm having a problem with the latest version (1.1.1.0)


nsjson::Set x /value []
nsjson::Get /exists x /end
Pop $R0
MessageBox MB_OK "$R0" ;yields "no", expected "yes"

nsjson::Set x /value [1]
nsjson::Get /exists x /end
Pop $R0
MessageBox MB_OK "$R0" ;yields "yes", as expected
To be clear, the previous version of the plugin (1.1.0.9) gives "yes" for the first snippet, as expected.