Yes. You can use cursors for that. In the following example rowlist contains list of affected ids. You can get it all at the end or get individual ids right before or after the update, or even decide on the update based on id/val values:

Class User.NewClass1 Extends %Persistent
{

Property val;

/// do ##class(User.NewClass1).Test()
ClassMethod Test()
{
   do ..%KillExtent()
   
   &sql(INSERT INTO NewClass1 SET val = 0)
   &sql(INSERT INTO NewClass1 SET val = 3)
   
   set rowlist = ""
   &sql(DECLARE NewClass1 CURSOR FOR
        SELECT %ID,val
        INTO :id, :val
        FROM NewClass1)
   
   &sql(OPEN NewClass1)
   for {
       &sql(FETCH NewClass1)
       quit:SQLCODE'=0
       set val2 = val*2
       write "Processing id: ", id,!
       set rowlist = rowlist _ $lb(id)
       &sql(UPDATE NewClass1 SET val = :val2 WHERE CURRENT OF NewClass1)
   }
   &sql(CLOSE NewClass1)
   
   zw rowlist
}
}

It would output in a terminal:

>do ##class(User.NewClass1).Test()
Processing id: 1
Processing id: 2
rowlist=$lb("1","2")

Documentation:

Here's an example:

Class User.NewClass1 Extends %Persistent
{

Property streams As list Of %Stream.GlobalCharacter;

ClassMethod Test()
{
    do ..%KillExtent()
    
    set obj = ..%New()
    set stream1 = ##class(%Stream.GlobalCharacter).%New()
    do stream1.WriteLine("Hi")
    set stream2 = ##class(%Stream.GlobalCharacter).%New()
    do stream2.WriteLine(123)
    
    do obj.streams.Insert(stream1)
    do obj.streams.Insert(stream2)
    write $System.Status.GetErrorText(obj.%Save())
    
    kill
    
    set obj = ..%OpenId(1)
    for i=1:1:obj.streams.Count() {
        write "Stream #", i, ": ", obj.streams.GetAt(i).Read($$$MaxCacheInt)
    }
}
}

Great article, however, I strongly disagree on the testing tools choice. Curl is not really the option, as CLI tools are really not the best for json editing. Upon the rest of your testing suggestions, I think there are better alternatives, such as:

  • REST clients: “Advanced REST Client” for Chrome and “REST Client” for Firefox, some are also available as a standalone applications
  • Debugging web proxies: Charles, Filddler etc. for the rare cases where REST clients do not offer enough information

The problem I see here is, if only one of the data object's properties has changed, how do we know which? Or do we simply overwrite all properties? 

If you use old json classes, you can send only changed properties, for example this json payload would be converted into  Sample.Person object with id=1 and all properties taken from disk except for Name property, which would be set to Bob:

{ _class: "Sample.Person", _id: 1, Name: "Bob" }

With new json you can get dynamic object from json with only modified properties and change persistent object by iterating over defined properties of a modified object.