%ZEN.proxyObject works alright with first empty element in a list. Here's a sample:

set json="{""Choices"":["""",10,20,30]}"
do ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(json,,.obj)
do ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(obj)

{
        "Choices":["",10,20,30
        ]
}

As for converting persistent objects to/from json, I would recommend first getting an example of json:

set obj = ##class(Driver.Entity).%OpenId(id)
do ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(obj)

Would output json from object of  Driver.Entity class. Then you can modify your json, so it would have the same structure. The important part is that json should contain _class property = Driver.Entity, this way %ConvertJSONToObject knows which class to convert json into.

You can determine class based on a path by enforcing one standard of internal<->external name conversion.

So you have two methods:

ClassMethod GetExternalName(InternalName) As %String {}
ClassMethod GetInternalName(ExternalName) As %String {}

And the value of expressions:

Write InternalName=..GetInternalName(..GetExternalName(InternalName))
Write ExternalName=..GetExternalName(..GetInternalName(ExternalName))

Is always 1 for any valid InternalName/ExternalName.

For every query (which can be a simple SQL query or a custom class query, here’s my post about them and their uses) QueryFunc method gets generated:

ClassMethod QueryFunc(Arg1, Arg2) As %SQL.StatementResult

which returns a %SQL.StatementResult used to iterate over the query. For example your Display query for LastName.BasicClassQuery class can be called from object context with this code:

Set ResultSet=##class(LastName.BasicClassQuery).DisplayFunc()
While ResultSet.%Next() { Write ResultSet.Name,! }

This is not, generally a good idea to insert potentially long and slow code inside of object constructor.

Why? %OnNew should contain code which is absolutely required on object initiation regardless of the execution speed. There is no use case for this class to construct an object and not call %Connect, so %Connect should be moved into %OnNew. That way client code needs to make one mandatory call instead of two.

Here's working example:

Class Sample.XSLTransform [ Abstract ]
{

ClassMethod test(tData = "<HHSOS><DIAGNOSES><DIAGNOSIS_DATA><DIAGNOSIS_DATA_GUID>3762875</DIAGNOSIS_DATA_GUID><DIAGNOSIS_DATA_GUID>37628752</DIAGNOSIS_DATA_GUID></DIAGNOSIS_DATA><DIAGNOSIS_DATA></DIAGNOSIS_DATA><DIAGNOSIS_DATA></DIAGNOSIS_DATA><DIAGNOSIS_DATA_GUID>37628753</DIAGNOSIS_DATA_GUID></DIAGNOSES></HHSOS>", tSelect = "//DIAGNOSIS_DATA_GUID[1]", tXSL = "ExampleXSL")
{
    set tXML= ##class(%GlobalCharacterStream).%New()
    do tXML.Write(tData)
    set tXSL=##class(%Dictionary.CompiledXData).%OpenId($classname() _ "||" _ tXSL ).Data

    kill tParams
    set tParams("selectParam") = tSelect
    set tSC=##class(%XML.XSLT.Transformer).TransformStream(tXML,tXSL,.tOutput,,.tParams)
    zwrite tSC
    set tSC=tOutput.OutputToDevice()
}

XData ExampleXSL
{
<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="selectParam"/>
<xsl:template match="/">
    <xsl:copy-of select="$selectParam"/>
</xsl:template>
</xsl:stylesheet>
}

}

Example:

Do ##class(Sample.XSLTransform).test()
tSC=1
<?xml version="1.0" encoding="UTF-8"?><DIAGNOSIS_DATA_GUID>3762875</DIAGNOSIS_DATA_GUID><DIAGNOSIS_DATA_GUID>37628753</DIAGNOSIS_DATA_GUID>

Time Stamp Specifications for Filenames - while configuring business operations and business services that transmit data to and from files, you can often specify input and output filenames in a string that includes date and time format codes, such as %Y%M%d%h%m%s_%f.txt. At runtime, the format codes within this string resolve dynamically based on the current date and time.

That's generally a questionable idea, here's why:

  • It's the slowest possible method - if we're iterating over result set the application logic may decide to end processing not after the last row but earlier. If a whole result set is returned, then we still spent CPU/RAM to calculate something we may not even need
  • Result set may be quite large which would cause application logic errors
  • Result set may be larger than amount of RAM available
  • Time to first result is usually smaller than getting all results, so the user can start working with the first row, while an application fetches more rows

Well, that depends.

  1. If an index definition includes an explicitly specified collation for a property, the index uses that collation.
  2. If an index definition does not include an explicitly specified collation for a property, the index uses the collation explicitly specified in the property definition.
  3. If the property definition does not include an explicitly specified collation, then the index uses the collation that is the default for the property data type.
  4. If the property data type does not include an explicitly specified collation, then the index uses namespace default collation
  5. If the namespace default collation is not specified, then SQLUPPER is used.