Indirection is your friend, which of course, works for globals, locals and other things too.

set ^myglobal="This is the root node"
set ^myglobal(12)="A node on level 1"
set ^myglobal(17)="More level 1 node"
set ^myglobal(17,1)="Data on the second level"
set ^myglobal(19,3)="More data on the second level"

; now start to play indirection
set someVariable="^myglobal" // the better way were: set someVariable=$name(^myglobal)

; and get the content of the above global
write @someVariable // --> This is the root node
write @someVariable@(12) // --> A node on level 1
write @someVariable@(17,1) // --> Data on the second level

; the same as above
set myVariable="^myglobal(17)" // Better: set myVariable=$name(^myglobal(17))
write @myVariable // --> More level 1 node
write @myVariable@(1) // Data on second level

; a bit overcomplicated
set string1="^"
set string2="myglobal"

write @(string1_string2_"("_(15+4_","_(1+2))_")") // --> More data on second level

So just (re)read the docu about indirection...

The error message <METHOD NOT SUPPORTED> says everything.

USER>s obj={"name":"john", "value":65}

USER>w obj.%ToJSON() // --> {"name":"john","value":65}

USER>s obj={"name":"john", "value":65, "dynObj":{"info":"something"} }

USER>w obj.%ToJSON() // --> {"name":"john","value":65,"dynObj":{"info":"something"}}

USER>s obj={"name":"john", "value":65, "dynObj":{"info":"something"}, "cosObj":(##class(%Net.HttpRequest).%New()) }

USER>w obj.%ToJSON() // --> <METHOD NOT SUPPORTED> *%ToJSON,%Net.HttpRequest

So the problem is, you try to "stringify" (JS-speech) a dynamic object, where one of the properties contains a non-dynamic object (%Net.HttpRequest in the above example).

Class DC.Samples Extends %RegisteredObject
{

/// partition an array into two subarrays
/// return [[even], [odd]]
ClassMethod Task1a(x As %DynamicArray) As %DynamicArray
{
	set t(0)=[],t(1)=[]
	for i=0:1:x.%Size()-1 do t(x.%Get(i)#2).%Push(x.%Get(i))
	quit [(t(0)),(t(1))]
}

/// partition an array into two subarrays
/// return [[even], [odd]]
ClassMethod Task1b(x As %DynamicArray) As %DynamicArray
{
	set t(0)=[], t(1)=[], i=x.%GetIterator()
	while i.%GetNext(,.v) {  do t(v#2).%Push(v) }
	quit [(t(0)),(t(1))]
}

/// hamming distance of two strings
ClassMethod Task2(x As %String, y As %String) As %Integer
{
	if $l(x)-$l(y) quit "<Error>"	// strings have to be the same length
	set r=0
	for i=1:1:$l(x) set r=$e(x,i)'=$e(y,i)+r
	quit r
}

/// encrypt an string
ClassMethod Task3(x As %String) As %String
{
	quit $tr($re(x),"aeiou","01223")_"aca"
}

/// check a string for identical chars
ClassMethod Task4(x As %String) As %Boolean
{
	quit $tr(x,$e(x))=""
}

/// double chars
ClassMethod Task5(x As %String) As %String
{
	f i=$l(x):-1:1 s $e(x,i)=$e(x,i)_$e(x,i)
	q x
}

}

For a handful of methods the manual method is likely the fastest... in case, you have a real big bunch of methods to copy put this "short" method into a class and let it run...

/// Transfer all or selected methods from a class into
/// individual classes
/// cls : the donor class
/// list: list of methods to be transfered: "method1,method2,..."
///       or empty to transfer all methods
ClassMethod Transfer(cls, list = "")
{
    s old=##class(%Dictionary.ClassDefinition).%OpenId(cls)
    s:list]"" list=$lfs(list)
    
    i old {
        f i=old.Methods.Count():-1:1 {
            s met=old.Methods.GetAt(i)				// grab the next method
            i list]"",'$lf(list,met.Name) continue	// skip if not to copy
            
            s new=old.%ConstructClone()				// duplicate old class
            s tmp=old.Name							// grab the old classname
            s $p(tmp,".",*)="Parts."_met.Name		// create a new classname
            s new.Name=tmp
            s new.Abstract=1						// make the class abstract
            s new.Super=""							// remove all superclasses
            
            s dup=met.%ConstructClone()				// duplicate the old method
            s dup.Name=met.Name						// but keep the old name
            d new.Properties.Clear()					// remove all properties
            d new.Parameters.Clear()				// remove all parameters			
            d new.Methods.Clear()					// remove all methods
            d new.Methods.Insert(dup)				// insert the copied method only
            d old.Methods.RemoveAt(i)				// Remove this method from old class
            i old.Super="" { s d="" } else { s d="," }
            s old.Super=old.Super_d_new.Name		// add the new class to extends-list
            s st=new.%Save()						// save the new class
            
            w new.Name,"-->",$s(st:"OK",1:$system.Status.GetOneErrorText(st)),!
            // Possibly compile the class: do $system.OBJ.Compile(...)
            
        }
        s st=old.%Save()							// save the old class
        w old.Name,"-->",$s(st:"OK",1:$system.Status.GetOneErrorText(st)),!
        // Possibly compile...
    }

If you want to reorder JSON properties (alphabetically or just put some of them at the beginning) then use a utility method, like this, especially if you have several object(types) to reorder

Class DC.Utility Extends %RegisteredObject
{
/// Reorder a JSON Object or Array
/// 
/// obj:  JSON-Object
/// 	  ord: prop1, prop2, ...	Desired order for (some) properties
/// 	       (Properties not listed are copied in the order in which they were created)
/// 	       If ord not present, properties will be reordered in aplphabetical order
/// 	       
/// obj: JSON-Array
/// 	 ord: pos1, pos2, ...	Desired order for (some) array items
/// 	      (Items not listed are copied in ascending order)
/// 	      
ClassMethod ReOrder(obj As %DynamicAbstractObject, ord... As %String)
{
	i obj.%Extends("%DynamicObject") {
		s new={}, itr=obj.%GetIterator()
		i '$g(ord) {
			while itr.%GetNext(.k) { s done(k)=0 }
			s k="" f  s k=$o(done(k)) q:k=""  d new.%Set(k,obj.%Get(k))
		} else {
			f i=1:1:$g(ord) { s k=ord(i),done(k)=1 d:$e(obj.%GetTypeOf(k),1,2)'="un" new.%Set(k,obj.%Get(k)) }
			while itr.%GetNext(.k,.v) { d:'$d(done(k)) new.%Set(k,v) }
		}
		
	} elseif obj.%Extends("%DynamicArray") {
		s new=[], itr=obj.%GetIterator(), max=obj.%Size(), done=""
		f i=1:1:$g(ord) { s k=ord(i) i k,k<=max d new.%Push(obj.%Get(k-1)) s $bit(done,k)=1 }
		while itr.%GetNext(.k,.v) { d:'$bit(done,k+1) new.%Push(v) }
		
	} else { s new=obj }
	
	q new
}
}

Some examples

s car={"color":"red", "fuel":"diesel", "maxspeed":150, "maker":"Audi", "model":"Quattro Q5", "power":300, "available":true, "rating":8, "allWheel":true }
s car1=##class(DC.Utility).ReOrder(car) // order all props alphabetically
s car2=##class(DC.Utility).ReOrder(car,"maker","model","available") // start with maker, model, etc.

w car.%ToJSON(),!,car1.%ToJSON(),!,car2.%ToJSON() --->
{"color":"red","fuel":"diesel","maxspeed":150,"maker":"Audi","model":"Quattro Q5","power":300,"available":true,"rating":8,"allWheel":true}
{"allWheel":"1","available":"1","color":"red","fuel":"diesel","maker":"Audi","maxspeed":150,"model":"Quattro Q5","power":300,"rating":8}
{"maker":"Audi","model":"Quattro Q5","available":"1","color":"red","fuel":"diesel","maxspeed":150,"power":300,"rating":8,"allWheel":"1"}

Is NOT the same. You can it prove by adding a label to the line with the read command and a new line at the end

    // DOT VERSION
    // Use fic
old Read *R:20 Else  Do  Quit    ;;;;  comando else aplicado a read.
    . Use 0 Write !!!,"Expired time."
    If $c(R)="a" d
    . Use 0 Write !!!,"A letter a has been read."
    . Quit
    write !,"If there are more lines, they will be executed",!
    quit

    // LITTLE BIT MODERN VERSION
    // Use fic
new Read *R:20
    If $Test {
    Use 0 Write !!!,"One character read"
    Quit
    }
    Else {
    Use 0 Write !!!,"Expired time."
    }
    write !,"If there are more lines, they will be executed",!
    quit
 

now let run both of them...

do old // let the timeout occur
do old // now with some input
do new // let the timeout occur
do new // now with some input

Do you see the difference? If there are more lines (at end) they will be executed in opposite cases (timeout/notimeout)

Things are not so easy as they seem, you have to consider scopes too. Take the above class (DC.LineNumber) and add three more methods:

ClassMethod CaseA(x)
{
    if x goto zTest
    quit "A0"
    
zTest quit "A1"
}

ClassMethod CaseB(x)
{
    if x goto Test
    quit "B0"
    
Test quit "B1"
}

ClassMethod Test()
{
    write ..CaseA(0),..CaseA(1) set linenumber=..SrcLineNumberFromStack(.routine,.label,.offset,.src) do prt
    write ..CaseB(1),..CaseB(0) set linenumber=..SrcLineNumberFromStack(.routine,.label,.offset,.src) do prt
    quit
    
    // debug
prt	write !,"routine: ",routine
    write !,"label: ",label
    write !,"offset: ",offset
    write !,"linenumber: ",linenumber
    write !,"src:",src,!!
}

and now do the test:

do ##class(DC.LineNumber).Test()

and check the output... 

OK, I know, this is a (very) constructed case and shouldn't coincide with an everyday development style, but who knows, what a mad programer sometimes produces...

If your serial class is named Data.Serial (as in your example code) then you should use the same name for the serial property too

Class Data.Persistent Extends %Persistent
{
Property MPID as %Integer;
Property Name as Data.Serial;   <--- !!!!!
}

The correct way to set the values

Set Obj=##Class(Data.Persistent).%New()
Set Obj.MPID=MPID
Set Obj.Name.FirstName=FirstName   ; <----
Set Obj.Name.LastName=LastName     ; <----
Set tSC=Obj.%Save()

I think, I have a solution for you

ClassMethod GetImage()
{
	s req=##class(%Net.HttpRequest).%New()
	s req.Server="www.distrelec.de"
	s req.SSLConfiguration="SSL"
	s req.ReadRawMode=1        //  <<---- this is your solution
	d req.Get("/Web/WebShopImages/landscape_medium/_t/if/sortimentsboxen-1.jpg")
	q req.HttpResponse
}

To get the image

s rsp=##class(Some.Class).GetImage()
i rsp.StatusCode=200 {
    s file="c:\temp\imageName.jpg"
    o file:"nwu":0
    i $t u file d rsp.Data.Rewind(),rsp.Data.OutputToDevice()
    c file
}

 That's all...

One of the problems could be the Bas64 encoding. This function inserts after each 76th byte a CRLF which possibly confuses the other party. Try with 

Set EncryptedBase64=$SYSTEM.Encryption.Base64Encode(encrypted, 1)

The parameter 1 says, do not insert CRLFs. Also, the text you encrypt must be an ANSI (8bit) text. If you are on a unicode system, you should call

Set encrypted=$SYSTEM.Encryption.AESCBCEncrypt($zcvt(text,"O","UTF8"),key,iv)

I do not use Ensemble, but I would try using the JSON-Adaptor, something like this

Class MessageB Extends (Ens.Request, %JSON.Adaptor)
{
   Property ClientId As %String(MAXLEN = "");
   Property message As %Stream.TmpBinary;
}

For example

s r=##class(MessageB).%New()
s r.ClientId=12345
d r.message.Write("part1")
d r.message.Write("part2")
w r.%JSONExportToStream(.s)
d s.Rewind()
w s.Read(s.Size) --> {"ClientId":"12345","message":"cGFydDFwYXJ0Mg=="}

Your solution is nearly perfect, here my quick (untested) version.


ClassMethod Encode()
{
	// You read N bytes (which MUST be divisible by 3) and write N*4/3 encoded bytes
	// 3 * 8190 = 24570; 24570 * 4 / 3 = 32760;  32760 < 32768; to avoid (slow) long strings
	set CHUNK=24570
	set NOCR=1	// don't insert CRLF after each 72 written bytes
	set encodedData=##class(%Stream.TmpBinary).%New() // adapt this to your needs: %Stream.Whatever...
	
	set request=##class(%Net.HttpRequest).%New()
	set request.Server="..."
    do request.Get("/...")
    
    if request.HttpResponse.StatusCode = 200 {
    	while 'request.HttpResponse.Data.AtEnd {
	    	do encodedData.Write($system.Encryption.Base64Encode(request.HttpResponse.Data.Read(CHUNK),1))
		}
	}
    QUIT encodedData
    
    // as an alternative, you could return a string or a streamobject
    set YOURMAXSTRING = 32767 // or 3641144
    if encodedData.Size <= YOURMAXSTRING {
	    do encodedData.Rewind()
	    quit encodedData.Read(encodedData.Size)
    } else { quit encodedData }
}

You are mixing two different things...

Property Data1 As list of %String;
Property Data2 As %List;

are two very different things. The first (Data1, equates to your DataObj.Services) is an object while the second one (Data2) is a simple scalar value (in this case a string which in its structure casually matches the inner structure of a $list() respective $listbuild() function).

write $listvalid(oref.Data1) ==> 0 // NOT a list
write $listvalid(oref.Data2) ==> 1 // a VALID list
write $isobject(oref.Data1) ==> 1  // a valid (list)object
write $isobject(oref.Data2) ==> 0  // not a valid (list)object

$listnext() does NOT work on objects (your DataObj.Services) is an object

For a string like "hallo" Cache will use 5+2 = 7 bytes. If that "hallo..." is longer then 253 bytes then length_of_string + 4 bytes will be used and if your "hallo..." is longer then 65535 bytes then length_of_string + 6 bytes will be used.

But there is one more thing, you should know: the sum of the lengths of ALL properties, except the array(like) properties, can't be greater then that famous 3641144 magic number (if you use the standard Cache Storage). Array-like properties are those, which are stored in own nodes.