CacheJSON is a JSON encoder/decoder for Intersystems Cache based applications and systems.
It can be used as a stand-alone utility class or extended inside your own custom classes to "JSON Enable" your objects.
A handy way to validate that the JSON is legal is to copy the string into this site http://json.parser.online.fr/
The primary features of CacheJSON are:
- Decode a single JSON object into an %ArrayOfDataTypes
- Decode nested arrays of JSON objects into a %ListOfObjects containing %ArrayOfDataTypes
- Decode a single JSON object into a custom Cache object
- Encode an %ArrayOfDataTypes to a JSON string
- Encode a custom Cache object class to a JSON string
- Encode a %ListOfObjects containing %ArrayOfDataTypes into a JSON string
- Embed an array as the value of an element
- Convert a Cache object instance into an %ArrayOfDataTypes
The original code originated from the Intersystem's Zen Google Group Community, however, the base for this class was taken from Yontan's Blog and added to GitHub by @mccrackendfor proper tracking of enhancements and maintenance.
Cache does not come with any native JSON support, necessitating a third party utility to translate JSON strings to & from Cache objects for web applications.
- For information about Intersystems products visit their website.
- Post to the Intersystems Zen Google Group for help or questions.
- See the GitHub issue tracker.
- Visit the Intersystems online documentation.
- Send a message to @PlanetCache on Twitter.
Import the class into your namespace and compile.
Then simply extend CacheJSON on the class you wish to use it with:
ClassSample.PersonExtends(%Persistent, %Populate,CacheJSON)[ClassType=persistent,Inheritance=right]Import the class into your namespace and compile.
Then call the CacheJSON class methods from your code.
SetencodedList=##class(CacheJSON).Encode(list)Below I'll go through some of the common uses and flows you can use with CacheJSON.
An %ArrayOfDataTypes is a simple Key/Value pair dictionary object used in Cache. CacheJSON will parse this object into a JSON string with the same key/value pairs contained in this object. Below is sample code to create this array and encode it to a JSON string.
SetmyArray=##class(%ArrayOfDataTypes).%New()DomyArray.SetAt("Dan","FirstName")DomyArray.SetAt("McCracken","LastName")DomyArray.SetAt("01/01/1983","DOB")SetjsonString=##class(CacheJSON).Encode(myArray)Creates a string like so:
{"DOB":"01/01/1983","FirstName":"Dan","LastName":"McCracken"}A %ListOfDataTypes is a simple array object used in Cache. Insert a bunch of %ArrayOfDataTypes into the list, and CacheJSON will translate this into a JSON array. Below is sample code using a list:
Setarr1=##class(%ArrayOfDataTypes).%New()Doarr1.SetAt("Dan","FirstName")Doarr1.SetAt("McCracken","LastName")Doarr1.SetAt("01/01/1983","DOB")Setarr2=##class(%ArrayOfDataTypes).%New()Doarr2.SetAt("Ron","FirstName")Doarr2.SetAt("Sweeney","LastName")Doarr2.SetAt("12/31/1978","DOB")Setlist=##class(%ListOfDataTypes).%New()Setsc=list.Insert(arr1)Setsc=list.Insert(arr2)SetencodedList=##class(CacheJSON).Encode(list)Creates a string like so:
[{"DOB":"01/01/1983","FirstName":"Dan","LastName":"McCracken"},{"DOB":"12/31/1978","FirstName":"Ron","LastName":"Sweeney"}]Set the value of an item to another %ArrayOfDataTypes. Example below:
Setmessage=##class(%ArrayOfDataTypes).%New()Domessage.SetAt("Posting to Campfire from Cache!","body")Setpayload=##class(%ArrayOfDataTypes).%New()Dopayload.SetAt(message,"message")SetjsonPost=##class(CacheJSON).Encode(payload)Creates a string like so:
{"message":{"body":"Posting to Campfire from Cache!"}}After you extend the persistent class with the CacheJSON class (see instructions above), you can call a method to simply project the object as a JSON string. Example below:
Setobj=##class(Sample.Person).%OpenId(1)SetjsonString=obj.GetJSONFromObject()Creates a string like so:
{"DOB":40434,"MyBool":null,"Name":"Bolt Usain","SSN":"722-81-1666"}Given a JSON string representing a single object:
{"DOB":57311,"Name":"Dan McCracken","SSN":"192-20-3003"}CacheJSON creates an %ArrayOfDataTypes object containing all the properties using the Decode() method.
SetmyDecodedArray=##class(CacheJSON).Decode(encodedString)Do $System.OBJ.Dump(myDecodedArray)
+----------------- generalinformation ---------------
| orefvalue: 3
| classname: %Library.ArrayOfDataTypes
| referencecount: 1
+----------------- attributevalues ------------------
| Data("DOB")=57311
| Data("Name")="Dan McCracken"
| Data("SSN")="192-20-3003"
| ElementType="%String"Given a JSON string representing an array of JSON objects:
[{"DOB":33997,"Name":"Koivu,Phyllis Z.","SSN":"676-82-4467"},{"DOB":61685,"Name":"Kelvin,Kristen S.","SSN":"546-95-9170"},{"DOB":53364,"Name":"DeLillo,Alexandra O.","SSN":"566-60-9488"}]CacheJSON will decode this array into a %ListOfDataTypes with nodes containing %ArrayOfDataTypes that represent each decoded object individually.
SetmyDecodedArray=##class(User.Util.CacheJSON).Decode(arrString)Do $System.OBJ.Dump(myDecodedArray)
+----------------- generalinformation ---------------
| orefvalue: 7
| classname: %Library.ListOfDataTypes
| referencecount: 1
+----------------- attributevalues ------------------
| Data(1)="12@%Library.ArrayOfDataTypes"
| Data(2)="14@%Library.ArrayOfDataTypes"
| Data(3)="16@%Library.ArrayOfDataTypes"
| ElementType=""
| Size=3 <Set>
Do $System.OBJ.Dump(myDecodedArray.GetAt(1))
+----------------- generalinformation ---------------
| orefvalue: 12
| classname: %Library.ArrayOfDataTypes
| referencecount: 1
+----------------- attributevalues ------------------
| Data("DOB")=33997
| Data("Name")="Koivu,Phyllis Z."
| Data("SSN")="676-82-4467"
| ElementType="%String"Given a JSON string with keys that map to a custom Cache object:
{"DOB":57311,"Name":"Dan McCracken","SSN":"192-20-3003"}When CacheJSON is extended on the object you're trying to map the JSON string to, you can create a new object containing the JSON values as properties using the GetObjectFromJSON() method.
USER> SetnewPerson=##class(Sample.Person).GetObjectFromJSON(encodedJSON)USER> WritenewPerson.NameDanMcCrackenThis is a helper method that will translate your object into an %ArrayOfDataTypes, allowing you to quickly build up a %ListOfDataTypes to Encode() as a return value for your methods. Using this method inside a quick loop generates a desired list:
Setlist=##class(%ListOfDataTypes).%New()Forx=1:1:3{Setobj=##class(Sample.Person).%OpenId(x)Setsc=list.Insert(obj.GetAsArrayOfDataTypes())}SetencodedList=##class(Sample.Person).Encode(list)This code generates an array of 3 JSON encoded Person objects that look like this:
[{"DOB":33997,"Name":"Koivu,Phyllis Z.","SSN":"676-82-4467","Spouse":null},{"DOB":61685,"Name":"Kelvin,Kristen S.","SSN":"546-95-9170","Spouse":null},{"DOB":53364,"Name":"DeLillo,Alexandra O.","SSN":"566-60-9488","Spouse":null}]There is a set of tests included in the repository that originated from Yontan's Blog that is a standard Cache %UnitTest.TestCase.
To run the test, use a command like:
Do##class(%UnitTest.Manager).RunTest("TestJSON:TestJSON","/noload/norecursive/nodelete")If you find something that looks like a bug:
- Check the GitHub issue tracker to see if it's a known issue.
- If you don't see anything, create an issue with information on how to reproduce it.
If you want to contribute an enhancement or a fix:
- Fork the project on GitHub.
- Make your changes and (optionally) update the test class.
- Commit the changes to your forked repo.
- Send a pull request.