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.

The documentation of the %ToJSON() method is correct and yes, you can do 

 do obj.%ToJSON()
 

merely, this works only "on devices without protocol" like terminal, (sequential) file, etc. Everywhere, wehere the data bytes goes direct to the target. WebSocket isn't such a device. There is a "header part", with information fields like the command, masking, the length of the data, etc.

You have two possibilities, a) you ask WRC for a "WriteStream()" method or b) you handle the whole WebSocket by hand (is not impossible) or c) you change your application logic and send the those messages in chunks.