Example

Result:

USER>##class(dc.test).Test("test"_$c(68))
gTNg0UMkvQ3o+ehJkvr6lA==

USER>##class(dc.test).Test("test"_$c(768))
R8UuZkjDVZidYckYMTpnVg==

USER>##class(dc.test).Test("测试")
lsYxFAQgNtiXHyaeGTWJ0A==
/// Encode a stream as BASE64
ClassMethod Base64EncodeStream(
  pStream As %Stream,
  Output pEncoded As %StreamAs %Status
{
  tSC=$$$OK
  try {
    tSC=pStream.Rewind()
    q:$$$ISERR(tSC)

    pEncoded=##class(%Stream.TmpCharacter).%New()
    while 'pStream.AtEnd {
      tLen=5700 
      tSC=pEncoded.Write($system.Encryption.Base64Encode(pStream.Read(.tLen)))
      q:$$$ISERR(tSC)
    }
    q:$$$ISERR(tSC)
        
    tSC=pEncoded.Rewind()
  catch (e{
    tSC=e.AsStatus()
  }
  tSC
}

Or something like that:

Class dc.test Extends %Persistent
{

Property Name As %String;

Property Age As %Numeric;

Property City As %String;

Property Phone As %String;

/// d ##class(dc.test).Test()
ClassMethod Test()
{
    do ..%KillExtent()
    
    // This is your Data-Object...

    ;set data="",data=[],data=..%New()

    set data=[
      {"Name":"Joe""Age":44"City":"Boston""Phone":"1-234-4567"},
      {"Name":"Ron""Age":48"City":"Dallas""Phone":"1-234-5678"},
      {"Name":"Eve""Age":40"City":"Miami",  "Phone":"1-234-4567"},
      ($listbuild("Tommy", 50, "New York""1-345-6789")),
      ($listbuild("Alexa", 35, "Portland""1-567-8901"))
    ]

    // Now insert all the above data into your table...
    &sql(
      INSERT INTO dc.test(Name,Age,City,Phone)
      SELECT $list(row,1),$list(row,2),$list(row,3),$list(row,4) 
      FROM dc.DataProvider(:data)
    )
    
    zwrite ^dc.testD

    // Now update your table...
    set data=[($listbuild("Vitaliy", 35, "Moscow""1-999-1234"))]

    &sql(
      UPDATE dc.test t
      SET t.Name=obj.Name
      FROM (SELECT $list(row,1) Name,$list(row,2) Age  FROM dc.DataProvider(:data)) obj
      WHERE t.Age=obj.Age
    )
    
    zwrite ^dc.testD
}

Query NewQuery1(dataAs %Query(ROWSPEC "row:%List") [ SqlName DataProviderSqlProc ]
{
}

ClassMethod NewQuery1Execute(
  ByRef qHandle As %Binary,
  dataAs %Status
{
  if $IsObject(data),data.%IsA("%Library.DynamicArray"),data.%Size() {

    set qHandle=data.%Size()+1

    for i=1:1:data.%Size() {
      set r=data.%Get(i-1)

      if $IsObject(r{
        set it=r.%GetIterator(),row=""
        while it.%GetNext(,.valset row=row_$listbuild(val} 

      } else {
        set row=r
      }
      set qHandle(qHandle-i)=$listbuild(row)
    }

  }

  quit $$$OK
}

ClassMethod NewQuery1Fetch(
  ByRef qHandle As %Binary,
  ByRef Row As %List,
  ByRef AtEnd As %Integer 0As %Status PlaceAfter = NewQuery1Execute ]
{
  if qHandle {
    set Row=qHandle($increment(qHandle,-1))
  else {
    set AtEnd=1
  }

  quit $$$OK
}

ClassMethod NewQuery1Close(ByRef qHandle As %BinaryAs %Status PlaceAfter = NewQuery1Execute ]
{
  quit $$$OK
}

Storage Default
{
<Data name="testDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>Name</Value>
</Value>
<Value name="3">
<Value>Age</Value>
</Value>
<Value name="4">
<Value>City</Value>
</Value>
<Value name="5">
<Value>Phone</Value>
</Value>
</Data>
<DataLocation>^dc.testD</DataLocation>
<DefaultData>testDefaultData</DefaultData>
<IdLocation>^dc.testD</IdLocation>
<IndexLocation>^dc.testI</IndexLocation>
<StreamLocation>^dc.testS</StreamLocation>
<Type>%Storage.Persistent</Type>
}

}

Result:

USER>##class(dc.test).Test()
^dc.testD=5
^dc.testD(1)=$lb("","Joe",44,"Boston","1-234-4567")
^dc.testD(2)=$lb("","Ron",48,"Dallas","1-234-5678")
^dc.testD(3)=$lb("","Eve",40,"Miami","1-234-4567")
^dc.testD(4)=$lb("","Tommy",50,"New York","1-345-6789")
^dc.testD(5)=$lb("","Alexa",35,"Portland","1-567-8901")
^dc.testD=5
^dc.testD(1)=$lb("","Joe",44,"Boston","1-234-4567")
^dc.testD(2)=$lb("","Ron",48,"Dallas","1-234-5678")
^dc.testD(3)=$lb("","Eve",40,"Miami","1-234-4567")
^dc.testD(4)=$lb("","Tommy",50,"New York","1-345-6789")
^dc.testD(5)=$lb("","Vitaliy",35,"Portland","1-567-8901")

With your permission I will add some useful links on the topic:

Using my simple example, when the method receive a name param or a age param to build the where clause. I really don't know how to solve it using query class.

Query FilterBy(
  Name As %String "",
  Age As %Integer ""As %SQLQuery(CONTAINID 1SELECTMODE "RUNTIME") [ SqlName SP_Sample_Filter_BySqlProc ]
{
SELECT TOP IDNameAgeSSN FROM Sample.Person
WHERE 
(nvl(:Name,'')='' or Name %STARTSWITH :Name)
AND
(nvl(:Age,'')='' or Age >= :Age)
}

Run Examples:
select * from Sample.SP_Sample_Filter_By(,47)
select * from Sample.SP_Sample_Filter_By('',47)

select * from Sample.SP_Sample_Filter_By('s',47)

select * from Sample.SP_Sample_Filter_By('s')
select * from Sample.SP_Sample_Filter_By('s','')
SELECT 

NVL(order_description,'') ||

CASE WHEN NVL(dosage,'')='' OR NVL(dosage_unit,'')='' THEN ''
     ELSE ', ' || dosage || ' ' || dosage_unit || CASE WHEN NVL(dosage_form,'')='' THEN ''
                                                       ELSE ' ' || dosage_form
                                                  END || ''
END ||

CASE WHEN NVL(administration_route,'')='' THEN ''
     ELSE ', ' || administration_route
END ||

CASE WHEN NVL(frequency_description,'')='' THEN ''
     ELSE ', ' || CASE WHEN NVL(quantity,'')='' OR NVL(quantity_unit,'')='' THEN ''
                       ELSE quantity || ' ' || quantity_unit || ' '
                  END || frequency_description
END ||

IFNULL(start_date,'',', ' || 'Start Date: ' || CONVERT(SQL_DATE,start_date,101)) As MedicationOrder

FROM CWSOrderEntry.history_client_order
WHERE PATID='100068'
--AND FACILITY=?FACILITY
AND order_status_code='A'
AND order_type_category_code='P'

Symbols Used in Caché SQL

SELECT 
(CASE WHEN (order_description IS NULL OR (order_description='')) THEN '' ELSE (order_descriptionEND) ||
(CASE WHEN (dosage IS NULL OR dosage_unit IS NULL OR (dosage='') OR (dosage_unit='')) THEN ''
ELSE (', ' || dosage || ' ' || dosage_unit || (CASE WHEN (dosage_form IS NULL OR (dosage_form='')) THEN '' ELSE (' ' || dosage_formEND) || ''END) ||
(CASE WHEN (administration_route IS NULL OR (administration_route='')) THEN '' ELSE (', ' || administration_routeEND) ||
(CASE WHEN (frequency_description IS NULL OR (frequency_description='')) THEN '' ELSE (', ' || (CASE WHEN (quantity IS NULL OR quantity_unit IS NULL OR (quantity='') OR (quantity_unit='')) THEN '' ELSE (quantity || ' ' || quantity_unit || ' 'END) || frequency_descriptionEND) ||
(CASE WHEN start_date IS NULL THEN '' ELSE (', ' || 'Start Date: ' || CONVERT(SQL_DATE,start_date,101)) ENDAs MedicationOrder
FROM CWSOrderEntry.history_client_order
WHERE PATID='100068'
--AND FACILITY=?FACILITY
AND order_status_code='A'
AND order_type_category_code='P'

Try changing the font, it's possible that you just have "||" displayed as "!!".

Using the JSON Adaptor.

Simple example:

Class dc.test Extends (%RegisteredObject%JSON.Adaptor)
{

Property list As list Of %String;

/// d ##class(dc.test).test()
ClassMethod test()
{
  json={"list":["green","yellow,red","blue"]}
  
  t=..%New()
  t.%JSONImport(json)
  t.list.Count(),!,t.list.GetAt(2)
}

}

USER>##class(dc.test).test()
3
yellow,red

Also look at Using Document Database (DocDB).

Another option without %ZEN.Auxiliary:

Class dc.mylist Extends %ListOfDataTypes
{

Method SizeSet(newvalue As %IntegerAs %Status
{
  i%Size=newvalue
  q $$$OK
}

}


Class dc.test Abstract ]
{

/// d ##class(dc.test).test()
ClassMethod test()
{
  json=["green","yellow,red","blue"]
  t=##class(%Document.Object).CSON(json.%ToJSON())
  
  l=##class(dc.mylist).%New()
  
  l.Data=t."_data"
  zk l.Data
  s l.Size=t.Count()
  
  l.Count(),!,l.GetAt(2)
}

}

Defining and Using Stored Procedures

 
Source code
Result:
select * from dc.daterange('1-5-2019','5-25-2019')
dBegin dEnd
01-05-2019 01-31-2019
02-01-2019 02-28-2019
03-01-2019 03-31-2019
04-01-2019 04-30-2019
05-01-2019 05-25-2019

Defining Stored Procedures

 
Source code
Result:
select * from dc.numbers(107)
n
1
2
...
105
106
107

Through %ZEN.proxyObject is unlikely to work, since the q parameter cannot be disabled in this case

q - output numeric values unquoted even when they come from a non-numeric property

Use your own class, for example:

Class dc.test Extends %RegisteredObject
{

Property articlenumber As %String;

}
object ##class(dc.test).%New()
object.articlenumber "15049950"

##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.json,object,,,,"aelotw")

Output:

{
  "articlenumber":"15049950"
}

Conclusion: the quote will be removed from the documentation since it's no longer true.

Then besides this, in the documentation for %STARTSWITH need to add the note DEPRECATED and the recommendation "use LIKE 'XXX%'"

I also did an analysis for Caché 2018.1

Class del.t Extends %Persistent
{

Index ip On p;

Property As %VarString;

/// d ##class(del.t).Fill()
ClassMethod Fill(1000000)
{
  DISABLE^%NOJRN
  ^del.tD,^del.tI

  i=1:1:^del.tD(i)=$lb("","test"_i)
  ^del.tD=N
  ENABLE^%NOJRN

  ..%BuildIndices(,,,$$$NO)
  d $system.SQL.TuneTable($classname(),$$$YES)
  d $system.OBJ.Compile($classname(),"cu-d")
}
}

Although the plans are exactly the same in SMP the results of the metrics differ:

select count(*from del.where like 'test7%'
Row count: 1 Performance: 0.291 seconds 333340 global references 2000537 lines executed

select count(*from del.where %startswith 'test7'
Row count: 1 Performance: 0.215 seconds 333340 global references 1889349 lines executed

For the next two queries, the INT code matches:

&sql(select * from del.where like 'test7%')
&sql(select * from del.where %startswith 'test7')

But for these - is already different, so the metrics in SMP are different:

&sql(select * from del.where like :a)
&sql(select * from del.where %startswith :a)

In IRIS 2020.1, the work with embedded queries was changed, but I can't check it.