class HS.JSON.Reader extends %Library.RegisteredObject
Utility class for reading JSON content and creating object instances from it. There are two methods to do this.
Approach #1: %ReadJSONIntoObject()
This approach is recommended in most cases.Examples:
Set tSC = ##class(HS.JSON.Reader).%ReadJSONIntoObject(.tObj,tJSON,"SomePackage.ExpectedClassName")
%ReadJSONIntoObject reads a JSON object into an instance of a registered object, taking into account the metadata of the target class (property types, etc.)
This may incur a slight performance overhead due to references to the class dictionary, but provides greater flexibility than %ReadJSON() to handle more complicated class definitions.
%ReadJSONIntoObject is also more secure than %ReadJSON, because the base expected class is part of the method signature and is used to validate the object type specified in JSON (by default, the _class property).
Approach #2: %ReadJSON()Example:
Set tSC = ##class(HS.JSON.Reader).%ReadJSON(tJSON,.tObj)
Internally, %ReadJSON() reads the input JSON into a local array (graph) and then copies the values within this array to objects it instantiates.
%ReadJSON treats the JSON as the authority for which properties to set in the target object. It does not use the class metadata for the target class, and therefore cannot know to avoid setting the values of stream, private, read-only, calculated, or multidimensional properties.
Use of %ReadJSON presents some minor security risks, because it may allow %New() to be called on an arbitrary class. This can be mitigated by subclassing, overriding %OnResolveObject(), and validating the the class against a hard-coded list of expected classes before calling %New().
%ReadJSON is best used to obtain an instance of %ZEN.proxyObject, or of a very simple registered class. It is also retained for backward-compatibility. New applications should use %ReadJSONIntoObject() in most circumstances.
This is called as each object is processed from the JSON input. It is responsible for creating an object to hold the data for the JSON input.
pData is the complete set of data processed from the JSON input. pNodeNo the node in pData containing the data for the current object.
Subclass can override this method.
pTypeField, if present, is the name of the JSON field that defines the server-side object class. By default this is "_class". If no type field is defined, %ZEN.proxyObject is used.
This differs from %ReadJSONIntoObject() in that %ReadJSON() does not consult class metadata. This makes it fast, but prevents it from being able to handle certain classes, and introduces some minor security risks.
pTypeField, if present, is the name of the JSON field that defines the server-side object class. By default this is "_class". This property only needs to be specified when the incoming data uses subclasses of the classes in the object tree referenced from an instance of pExpectedType.
Set pCacheMode = 0 to disable class metadata caching.
This differs from %ReadJSON() in that the class metadata for the expected type is consulted. This introduces a performance overhead, but also enables reading in of some types that %ReadJSON() does not support (for example, classes with calculated, read-only, and private properties).