Kenneth, what is the use case for this? If you want to move Global data around, there are clearly optimized APIs for this task.

If you want to store JSON-like data you should be looking into the Document Data Model that is introduced with Caché 2016.2. The %ZEN.proxyObject has an interface for persisting dynamic data as well, but it clearly has been superseded by the new JSON capabilities available in Caché 2016.1 and up.

Without understanding your requirements, there are two potential approaches how you can serialize a Global in a JSON structure. One way is to represent the Global with a top-level object and all nodes in one big array. Each node is represented by an object, which includes the subscript as an array:

{"GlobalName":"Person","nodes":[

{"subscript":[],"value":1},

{"subscript":[1],"value":"Smith,John^M^1968-01-12"},

{"subscript":[1,"Address"],"value":"123 Main Street^Some City^CA^92627"}

]}

This serialization is easy to generate and consume as well. The complete subscript is available within each object, which makes the (de-)serialization logic simple. The downside of this approach is that you can only represent a Global as a whole. You could enhance this approach to start at a specific subnode, but you can not easily filter for specific sub-paths.

Another approach is to nest subnodes. This makes the (de-)serialization logic more complex as it has to be recursive:

{"GlobalName":"Person","nodes":[

{"subscript":[],"value":1,"children":[

{"subscript":[1],"value":"Smith,John^M^1968-01-12","children":[

{"subscript":["Address"],"value":"123 Main Street^Some City^CA^92627"}

]}

]}

]}

This allows you to easily skip sub-paths during processing, but the processing logic gets more complex. I realize there are more variations how you can represent a Global in JSON format, but I think there are two fundamental approaches, flat and nested.

Again it depends on what you want to achieve. I would be interested in learning more about what you have in mind.

I would like to add that $zf(-3) and $zf(-4,1) calls can only be used to load what we call a callout library. This is a specific DLL that properly exports functions during linking and  exposes them in a ZFENTRY table. You can find more material about the callout gateway in this part of the documentation:

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

If you want to work with a specific DLL that is not a callout library, you have to wrap the library, e.g. in a Java jar library or a callout DLL and then call out from Caché Object Script.

The project Evgeny mentioned may be of help as well.

You are on the right path. Zen Mojo 1.1.0 prevented the drop-down menu from closing because we did not bubble up the event. We addressed this issue in Zen Mojo 1.1.1.

Make sure to upgrade to the latest version of Zen Mojo. You have to return false in your onselect event handler to allow the event to bubble up which will automatically close the drop-down menu after the user selected an item. 

If it is more complex to determine the data set, because you have specific parameters in mind it makes sense to select the data via SQL and insert the selected record into the other instance via SQL. You can either use linked tables, which allows you to write this simple logic in Caché Object Script, or you can write a simple Java application and go directly via JDBC. Obviously, any supported client-side language can solve this challenge, Java is just one option.

In case you have to migrate data where the model includes foreign-key constraints, you have to use the %NOCHECK keyword in your SQL INSERT statement: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

This approach is definitely more work than just exporting/importing the data, but it allows to easily add simple logic with some benefits, e.g. anonymization, batch-loading and parallelization. Depending on your use case some of these topics may be relevant.

The $toJSONFormat() method provided a way to output a formatted (pretty-printed) JSON string/stream. There is an effort involved to make sure such a method works properly on all supported platforms (which it didn't) and in addition, there are various options that users would ask for (like omitting null values, intent or no intent, intent with spaces, etc...). We had a similar experience with the previous JSON API.

We decided to put our initial efforts into the machinery and not into pretty-printing. For that reason, we do not produce any output that is irrelevant for machine processing, which is the major task for this output as JSON is a data-interchange format.

It is very simple to post-process a JSON file or string and pretty-print or minify it. There are online tools like

http://www.freeformatter.com/json-formatter.html

and there is functionality/plugins available for popular text editors like Sublime 3:

https://github.com/dzhibas/SublimePrettyJson

Also, there are many node.js packages available that pretty-print or minify JSON files and that can be automated with a grunt/gulp task if you have to automate this for some reason. 

Personally, I just copy/paste my JSON content into Sublime3 and pretty print it.

That is correct. If you expect to serve larger JSON content you should make use of the stream interface as Dmitry has pointed out. Here is a snippet that copies the content of a dynamic object to a local file on windows:

ClassMethod WriteObjectToFile(pObject As %Object)
{

set stream=##class(%Stream.TmpCharacter).%New()
set filestream=##class(%Stream.FileCharacter).%New()
set sc=filestream.LinkToFile("c:\Temp\jsonfile.txt")
do pObject.$toJSON(stream)

do filestream.CopyFrom(stream)
do filestream.%Save()

}

Hm, interesting. So what this basically means is that the 404 page gets cached when a URL is requested and it is not available. Re-enabling the REST application does not clear that cache and that is the reason why the REST application does not work for the URLs that have the 404 cached when it's enabled again.

Automatically clearing the cache for a REST application is not trivial, as it does not translate to a single URL. I will check back with the developers and see what we can do about this.

Well, that depends on where you did take the lock.

In your previous example you take a lock right before the try block, so you can release it directly after the try/catch block.

If you take a lock in your try block, you have to put the unlock code both in the catch block and at the end of the try block. I would not place the unlock code outside of the try/catch block. This is a case where a try/catch/finally construct would definitely help, as you could place the unlock code in the finally block.