Not in the near-term. We are using a highly optimized in-memory and on-disk structure for our JSON support and the document data model. Providing more features and adding more optimizations to this structure stays a priority.

Our model allows us to support other serialization formats as well and we have some hooks in place we plan to leverage in the future. MessagePack and other serializations are on the tentative list for this, but nothing is carved in stone at the moment.

Do you have a specific use case where MessagePack is a requirement?

Well, I think a major question is: What do you use to return runtime information to your caller when you implement your own code? Do you return a %Status object, or something similar, or do you throw exceptions and don't return anything.

Most code snippets I have seen here make use of try/catch, but do return a status code itself. 

Personally, I prefer to use try/catch blocks and throw errors when I encounter issues at runtime. The try/catch philosophy is optimized for the case that everything goes well and exceptions are the, well, exception. Handling a status object is not as clean from a code maintenance perspective (more lines of code within your logic), but allows you to handle multiple different scenarios at once (it was okay/not okay, and this happened...)

Obviously, this is my personal preference.

do a.$toJSON() does not work properly with I/O redirection. This is a known issue and will be fixed in future releases. The workaround is very simple: use write a.$toJSON(), or write something else to the stream before (like you did in your second example).

Personally, I prefer to be explicit in my REST methods and use the write command when I want to output something to the response stream. So this code snippet will work in your REST class:

ClassMethod Test() As %Status
{
set "test":}
write a.$toJSON()
quit $$$OK
}

Jochen's approach is one way of dealing with this scenario. Another approach is to always inject the header and footer layout and drive the content with a data binding. This way you can always include your generic header/footer layout objects in all of your pages. This approach also allows you to implement your header and footer logic in a central method, so you don't duplicate code.

If you want more sophisticated control, you can easily build your own plugin and implement your own header/footer components with specialized logic and behavior.

As the others, I am trying to guess what you mean when you say organizing code. I can think if source control, project organization and auto code formatting.

If you get more specific we can provide a better answer. If you are not aware of Atelier, our new Eclipse-based IDE, take a look at the session recording from Global Summit 2016:

https://beta.learning.intersystems.com/mod/page/view.php?id=212

I am not sure if this helps, but I want to mention that Ensemble comes with an option to export all classes and routines that are required to run an Ensemble production. At least, all dependencies Ensemble can resolve.

You can find the related documentation here:

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

Maybe you can take a look at the code behind the scenes, or analyze the output of such an export.

We have no way to represent these special JSON values in Caché Object Script. When you access these special values they are automatically converted to a friendly Caché Object Script value. Here is some more code to describe this based on the snippets I used before:

USER>write object.$getTypeOf("boolean")
boolean
USER>write object.$getTypeOf("nullValue")
null
USER>write object.$getTypeOf("numeric")
number
USER>write object.boolean
0
USER>write object.anotherBoolean
1

You can see, that I can retrieve the type for each property using the $getTypeOf() method. The boolean property returns 0 while the anotherBoolean property returns 1. Both are Caché Object Script-friendly and allow embedding in if-statements.

We would have lost that capability if we introduced special Caché Object Script values to reference special JSON values. In addition, you have to have in mind, that we plan to introduce more serialization formats in the future, so we may not only talk about special JSON values here.

Does that make sense?

I see. Serializing registered and persistent objects to JSON is a new feature in 2016.2. $toJSON() allows you to serialize these objects using a standard projection algorithm that we provide. There are ways how you can specify your own projection logic, in case the standard logic is insufficient for your needs.

$compose() is a new method that lets you project dynamic entities (%Object and %Array instances) to registered and persistent objects (and vice-versa).

The $compose functionality is using the same standard projection logic. Later versions will allow you to specify and store projection rules for specific needs.

Absolutely. If you are using the embedded JSON-style constructor you can directly make use of special values:

USER>set object = {"boolean":false,"numeric":2.2,"nullValue":null}
 
USER>write object.$toJSON()
{"boolean":false,"numeric":2.2,"nullValue":null}

If you want to manipulate or add special values like null and true/false, you have to use the setter method $set and specify the type with the optional third argument:

USER>do object.$set("anotherBoolean",1,"boolean")
 
USER>write object.$toJSON()
{"boolean":false,"numeric":2.2,"nullValue":null,"anotherBoolean":true}
If I wouldn't have specified the type in the above sample, the value would have been set to the numeric value 1.
HTH,
Stefan

I just tested this in a 2016.2 FieldTest terminal session:

USER>set object = {"":"test"}
 
USER>w object.$toJSON()
{"":"test"}
USER>set object."" = "one more test"
 
USER>w object.$toJSON()
{"":"one more test"}

So the answer is, yes we do support empty keys.

We have and continue to test our JSON implementation heavily. If you come across anything that looks incomplete, incorrect or just behaves in unexpected ways, let us know. We are happy to take a look at it.

Many thanks, Stefan

There is no easy way to achieve this on the server side. But you can easily extract the currently displayed data set on the client. Here is a code snippet that works with the tablePane demo ZENTest.TableTest.cls in the SAMPLES namespace:

var t = zen('table')
for (var i = 0;i < t.pageSize; i++) { console.log(t.getRenderedRowData(i)) }

The code snippet will render each individual row, respecting the current filtering and order.

Ha, this post really made me laugh out loud. But I do see use cases for this kind of an integration. If you use slack for issue tracking you can easily create  a channel where all Ensemble issues are automatically posted. Inactive Business Services, thrown errors, etc. If Slack is part of your company culture, this is a simple and nice enhancement to your workflow. 

Also, if you are using the System Management Portal to activate a new key, make sure to double check the capabilities of the new key. You will be presented with a popup that displays the new key, so you can make sure that you really selected the correct key for activation (e.g. correct platform, all required features).

Activating a new key does not require a system restart unless there are major differences between the old and the new key. As an example: If the new key enables the same number of users (or more) a restart is not required. Downgrading the user count will require a system restart. 

The error means that the version of your Java runtime is too old. For more information on this error, please see a related stackoverflow thread:

http://stackoverflow.com/questions/10382929/how-to-fix-unsupported-major...

Recent versions of Caché and Ensemble only support Java 7 and 8, as Java 6 has reached end-of-life and has multiple security flaws.

Upgrade your Java runtime to 7 or 8 and the error will go away.