Practical ObjectScript Coding: From JSON to Globals to SQL
While starting with Intersystems IRIS or Cache, developers often encounter three core concepts: Dynamic Objects, Globals & Relational Table. Each has its role in building scalable and maintainable solutions. In this article, we'll walk through practical code examples, highlight best practices, and show how these concepts tie together.
1. Working with Dynamic Objects:
Dynamic objects (%DynamicObject and %DynamicArray) allow developers to manipulate JSON-like structures directly in Objectscript. They are especially useful for modern applications that need to parse, transform or generate JSON.
Example: Creating & Manipulating Dynamic Objects
// Create a Dynamic object
Set obj - {}
// Add properties
Set obj.name = "Vachan"
Set obj.age = 25
// Nested objects
Set obj.address = {"city":"Bengaluru", "zip":"560000"}
// Add an Array
Set obj.skills = ["Objectscript", "SQL"]
// Convert to JSON string
Set json = obj.%ToJSON()
Write json,!
// Parse JSON string back to an object
Set parser = {}.%FromJSON(json)
Write parser.nameBest Practices:
- Always validate JSON input with %FromJSON() to catch errors.
- Use obj.%Get("property") when unsure if a property exists.
- Favor %DynamicArray for list-like structures.
2. Using Globals Effectively:
Globals are hierarchical sparse arrays stored directly in the IRIS database engine. They are extremely fast and can store virtually any structure.
Example: Storing Data in Globals
// Store student data in a global
SET ^Student(1,"Name") = "Alice"
SET ^Student(1,"Age") = 29
SET ^Student(2,"Name") = "Bob"
SET ^Student(2,"Age") = 34
// Retrieve data
WRITE ^Student(1,"Name") // outputs: Alice
// Iterate over all students
SET id=""
FOR SET id=$ORDER(^Student(id)) QUIT:id="" {
WRITE "Student ",id,": ",^Student(id,"Name")," (Age ",^Student(id,"Age"),")",!
}Best Practices:
- Define a clear global structure before coding (avoid ad-hoc keys).
- Use globals for high-performance storage when SQL overhead is not needed.
- For application data, prefer persistent classes with globals managed under the hood.
3. Creating Relational SQL tables:
In IRIS, relational tables can be created using both SQL DDL and persistent classes.
Example: Creating a SQL Table via DDL
CREATE TABLE Employee (
ID SERIAL PRIMARY KEY,
Name VARCHAR(50),
Age INT,
Department VARCHAR(50)
);Example: Creating the same table as a Persistent Class
Class Company.Employee Extends (%Persistent) {
Property Name As %String(MAXLEN=50);
Property Age As %Integer;
Property Department As %String(MAXLEN=50);
}Once compiled, this class automatically creates an underlying global and an SQL table. You can now use both ObjectScript and SQL:
// Create and save an employee
SET emp = ##class(Company.Employee).%New()
SET emp.Name = "Charlie"
SET emp.Age = 40
SET emp.Department = "IT"
DO emp.%Save()
// Query employees with SQL
&sql(SELECT Name, Age FROM Company.Employee)
WHILE (SQLCODE=0) {
WRITE "Employee: ",Name,", Age: ",Age,!
FETCH NEXT
}Best Practices:
- Prefer persistent classes for maintainable applications.
- Use SQL DDL for quick table definitions or integration with external systems.
- Always define indexes for commonly queried properties.
SUMMARY:
Whether you are parsing JSON payloads, managing high-speed lookup data, or designing relational tables, understanding when to use dynamic objects, globals, or persistent classes is key to becoming an effective ObjectScript developer.
Comments
instead of having each property stored with its name as a subscript, (e.g. ^Student(1,"Name") = "Alice" / ^Student(1,"Age") = 29 etc.)
its much better to use the same format the class compiler is storing data on the D global:
^Student(1)=$LB("Alice",29 ... )
when having globals with millions (or billions) of records it will have a huge impact on performance and storage footprint.
Instead of using obj.%Get("property"), you can use %IsDefined("key"), which returns 1 if the key exists.
You can also use %Get("key",, "type"), where the optional type parameter specifies the expected return type. This helps prevent <MAXSTRING> errors when handling values near IRIS's maximum string length.
To enable native JSON support in a persistent class, extend %JSON.Adaptor. This provides built-in methods such as:
%JSONImport()— Imports a JSON or DAO directly into the object.%JSONExport()— Export and display the value in the device%JSONExportToString()— Export the value as a string.%JSONExportToStream()— Export the value as a stream
Class Company.Employee Extends (%Persistent,%JSON.Adaptor) {
Property Name As %String(MAXLEN=50);
Property Age As %Integer;
Property Department As %String(MAXLEN=50);
ClassMethod LoadData() As %Staus
{
Set json = {"Name":"Test", "Age": 20, "Department": "IT"}
Set obj = ..%New()
Set sc = obj.%JSONImport(json)
Set sc = obj.%Save()
Return sc
}
ClassMethod ExportDataAsJSONString(Id) As %String
{
Set obj = ..%OpenId(Id)
Do obj.%JSONExportToString(.string)
Return string
}
ClassMethod ExportDataAsJSONStream(Id) As %Steam.Object
{
Set obj = ..%OpenId(Id)
Do obj.%JSONExportToStream(.stream)
Return stream
}
}If you're working with classes, it's recommended to use object-based or SQL-based data manipulation rather than directly using globals.