Send byte array from c# to angular through websocket - c#

Hi I would like to implement a function that a byte array is sent from C# to my Angular 7 through websocket. Basically, I have a websocket running with C# and my frontend is written in Angular7.
Please note, the following example is a simplified one. In my real application, the object I am going to send includes about 400 fields. After serialise the object to json string, it is about 6kb. In addition, I need to send 30 such objects in about one second. Sending binary data will significantly reduce the package size and speed it up.
In C#, I have such example code to generate the payload of the websocket:
public class Test
{
public int Id { get; set; }
public float Value { get; set; }
public string Description { get; set; }
}
public class Payload
{
public object Obj { get; set; }
}
Test[] tests = new Test[]
{
new Test
{
Id = 0,
Value = 1.12f,
Description = "The First Test"
}
};
byte[] testsByteArray;
using (MemoryStream m = new MemoryStream())
{
using (BinaryWriter binaryWriter = new BinaryWriter(m))
{
foreach (Test test in tests)
{
binaryWriter.Write(test.Id);
binaryWriter.Write(test.Value);
binaryWriter.Write(test.Description);
}
}
testsByteArray = m.ToArray();
}
Payload payload = new Payload
{
Obj = testsByteArray
};
string a = JsonConvert.SerializeObject(payload);
Eventually I got a as {"Obj":"AAAAAClcjz8OVGhlIEZpcnN0IFRlc3Q="} I guess the value of Obj is base64 encoded value of testsByteArray.
Now, in my frontend, I can receive the json string. The question is how to convert AAAAAClcjz8OVGhlIEZpcnN0IFRlc3Q= back to an object with the same format as Test in Angular.
What I tried:
I tried to use the following function atob() to decode the base64, and then use the following function to convert the decoded string to byte array
str2ab(str): ArrayBuffer {
var buf: ArrayBuffer = new ArrayBuffer(str.length * 2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
Then I try to use the following code to get the values
let dataView = new DataView(arrayBuffer);
console.log(dataView.getInt32(0)); // = 0
console.log(dataView.getInt32(2)); // = 0
console.log(dataView.getInt32(4)); // = 0
console.log(dataView.getInt32(6)); // = 10496
I am not exactly sure how to convert to correct value. Can anyone help out.
Thank you

Sending binary data between different platforms and languages is fragile and difficult to get right. I'd suggest converting to a platform agnostic representation (such as a JSON array) before sending, and convert back on the other side.
For example,
string a = JsonConvert.SerializeObject(tests);

Related

Why are the arrays null when I'm sending form data using .NET API and React?

DTO looks like this:
public List<IFormFile> Images { get; set; }
public int[] Numbers { get; set; }
Method Signature:
public async Task<IActionResult> AddSection([FromForm]TheDto theDto)
Add the form data in React:
const handleSubmit = (data: any) => {
const formData = new FormData();
for(const name in data) {
formData.append(name, data[name]);
}
postService.addSection(formData);
}
It's then sent using axios.
Other values go through fine which are not in an array. I've inspected the data being added to FormData and the data is correct, I have 2 arrays, one holding File[], the other holding number[] and the names match that of the DTO so I'm now at a loss. Have I missed something?
I've used the same method on a single image and that's worked fine.
Edit:
If I log data in the above function, data has this:
{images: Array(2), numbers: Array(3)}
images: (2) [File, File]
numbers: (3) [40, 43, 77]
Further edit:
I can see that the issue is that when I'm appending the data, I'm only adding the string value for the arrays. So I think that the 2 issues are making sure I'm appending the data in the arrays properly and in a way that the .NET array understands to bind the data correctly.
There may be a better way of doing this and I'd be happy to listen to any better ways but I changed the way I appended the data for the arrays, it's now working ok.
for(const name in data) {
if (Array.isArray(data[name]) {
for (let i = 0; i < data[name].length; i++) {
formData.append(name, data[name][i]);
}
} else {
formData.append(name, data[name]);
}
}

Converting large httpresponse stream to a JSON string?

Question Background:
Update:
I'm still not sure how to go about extracting the relevant information from this response. I have tried setting my response type to JSON but still receive the response as shown below. I have taken into account what has been said in regards to using NameValueCollection but still cant see how this will help with such a large response. Ideally I'd like this mapped to an object structure of some kind, it dosen't necessarily have to be JSON.
Question:
I'm currently using the PayPal Api 'ExpressCheckout' method to allow users to pay for items on my test site. A HTTP response from the API provides a large response containing key information I need to extract - such as the buyers address, if the payment was succesful etc.
The Issue:
Currently I'm stuck on how to work with the response. Ideally I'd convert the data to a JSON string then use Newtonsoft to map the data to C# classes thus allowing easy access to the data. Here is an example of the Httpresponse:
TOKEN=EC%2XXXXXXXXXXXXXXXXXR&BILLINGAGREEMENTACCEPTEDSTATUS=0&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2015%2d01%2d02T21%3a11%3a30Z&CORRELATIONID=ab184fdba7a30&ACK=Success&VERSION=88%2e0&BUILD=14443165&EMAIL=test%40aol%2ecom&PAYERID=3XXXXXXXXXX4N&PAYERSTATUS=verified&BUSINESS=Test%20Biz%27s%20Test%20Store&FIRSTNAME=Joe&LASTNAME=King&COUNTRYCODE=GB&SHIPTONAME=Joe%20King%27s%20Test%20Store&SHIPTOSTREET=1%20Main%20Terrace&SHIPTOCITY=Wolverhampton&SHIPTOSTATE=West%20Midlands&SHIPTOZIP=W12%204LQ&SHIPTOCOUNTRYCODE=GB&SHIPTOCOUNTRYNAME=United%20Kingdom&ADDRESSSTATUS=Confirmed&CURRENCYCODE=GBP&AMT=15%2e56&ITEMAMT=15%2e56&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&TAXAMT=0%2e00&INSURANCEAMT=0%2e00&SHIPDISCAMT=0%2e00&L_NAME0=ItemOne&L_QTY0=4&L_TAXAMT0=0%2e00&L_AMT0=3%2e89&L_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUEST_0_CURRENCYCODE=GBP&PAYMENTREQUEST_0_AMT=15%2e56&PAYMENTREQUEST_0_ITEMAMT=15%2e56&PAYMENTREQUEST_0_SHIPPINGAMT=0%2e00&PAYMENTREQUEST_0_HANDLINGAMT=0%2e00&PAYMENTREQUEST_0_TAXAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEAMT=0%2e00&PAYMENTREQUEST_0_SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUEST_0_SHIPTONAME=Joe%20King%27s%20Test%20Store&PAYMENTREQUEST_0_SHIPTOSTREET=1%20Main%20Terrace&PAYMENTREQUEST_0_SHIPTOCITY=Wolverhampton&PAYMENTREQUEST_0_SHIPTOSTATE=West%20Midlands&PAYMENTREQUEST_0_SHIPTOZIP=W12%204LQ&PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=GB&PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=United%20Kingdom&PAYMENTREQUEST_0_ADDRESSSTATUS=Confirmed&L_PAYMENTREQUEST_0_NAME0=ItemOne&L_PAYMENTREQUEST_0_QTY0=4&L_PAYMENTREQUEST_0_TAXAMT0=0%2e00&L_PAYMENTREQUEST_0_AMT0=3%2e89&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUESTINFO_0_ERRORCODE=0
If anyone could give me an easy way to map this data to a C# object that would be great.
Is there any specific reason why you want it in JSON format? If its not requirement and if you can live with key value pair then here is one way you can process response as key value pair.
public partial class Form1 : Form
{
Dictionary<string, string> processedResponse = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string rawResponse = "TOKEN=EC%2XXXXXXXXXXXXXXXXXR&BILLINGAGREEMENTACCEPTEDSTATUS=0&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2015%2d01%2d02T21%3a11%3a30Z&CORRELATIONID=ab184fdba7a30&ACK=Success&VERSION=88%2e0&BUILD=14443165&EMAIL=test%40aol%2ecom&PAYERID=3XXXXXXXXXX4N&PAYERSTATUS=verified&BUSINESS=Test%20Biz%27s%20Test%20Store&FIRSTNAME=Joe&LASTNAME=King&COUNTRYCODE=GB&SHIPTONAME=Joe%20King%27s%20Test%20Store&SHIPTOSTREET=1%20Main%20Terrace&SHIPTOCITY=Wolverhampton&SHIPTOSTATE=West%20Midlands&SHIPTOZIP=W12%204LQ&SHIPTOCOUNTRYCODE=GB&SHIPTOCOUNTRYNAME=United%20Kingdom&ADDRESSSTATUS=Confirmed&CURRENCYCODE=GBP&AMT=15%2e56&ITEMAMT=15%2e56&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&TAXAMT=0%2e00&INSURANCEAMT=0%2e00&SHIPDISCAMT=0%2e00&L_NAME0=ItemOne&L_QTY0=4&L_TAXAMT0=0%2e00&L_AMT0=3%2e89&L_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUEST_0_CURRENCYCODE=GBP&PAYMENTREQUEST_0_AMT=15%2e56&PAYMENTREQUEST_0_ITEMAMT=15%2e56&PAYMENTREQUEST_0_SHIPPINGAMT=0%2e00&PAYMENTREQUEST_0_HANDLINGAMT=0%2e00&PAYMENTREQUEST_0_TAXAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEAMT=0%2e00&PAYMENTREQUEST_0_SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUEST_0_SHIPTONAME=Joe%20King%27s%20Test%20Store&PAYMENTREQUEST_0_SHIPTOSTREET=1%20Main%20Terrace&PAYMENTREQUEST_0_SHIPTOCITY=Wolverhampton&PAYMENTREQUEST_0_SHIPTOSTATE=West%20Midlands&PAYMENTREQUEST_0_SHIPTOZIP=W12%204LQ&PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=GB&PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=United%20Kingdom&PAYMENTREQUEST_0_ADDRESSSTATUS=Confirmed&L_PAYMENTREQUEST_0_NAME0=ItemOne&L_PAYMENTREQUEST_0_QTY0=4&L_PAYMENTREQUEST_0_TAXAMT0=0%2e00&L_PAYMENTREQUEST_0_AMT0=3%2e89&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUESTINFO_0_ERRORCODE=0";
//Process response
processedResponse = ProcessResponse(rawResponse);
//Use received data e.g.
//Get First name
string fName = GetRecordValue("FIRSTNAME");
//Get Last name
string lName = GetRecordValue("LASTNAME");
}
private Dictionary<string,string> ProcessResponse(string response)
{
Dictionary<string, string> responseData = new Dictionary<string, string>();
if(!string.IsNullOrWhiteSpace(response))
{
string[] firstPass = response.Split(new char[] { '&' });
foreach(string pair in firstPass)
{
string[] secondPass = pair.Split(new char[] { '=' });
if(secondPass!=null && secondPass.Length>0)
{
responseData.Add(secondPass[0].Trim(), secondPass[1].Trim());
}
}
}
return responseData;
}
private string GetRecordValue(string record)
{
string recordValue = null;
if(processedResponse!=null)
{
if(!string.IsNullOrWhiteSpace(record) && processedResponse.ContainsKey(record))
{
recordValue= processedResponse[record];
}
}
return recordValue;
}
}
Still unsure what's the problem with dealing with it as a NameValueCollection.
E.g.
//NameValueCollection
//or use HttpUtility.ParseQueryString(some_string_of_names_values)
var foo = Request.QueryString;
var bar = foo["FIRSTNAME"]; //based on above this is "Joe"
Update:
It is response string which is being processed here and not request hence you wont be able to retrieve details using Request.QueryString
As stated in comments:
string rawResponse = "TOKEN=EC%2XXXXXXXXXXXXXXXXXR&BILLINGAGREEMENTACCEPTEDSTATUS=0&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2015%2d01%2d02T21%3a11%3a30Z&CORRELATIONID=ab184fdba7a30&ACK=Success&VERSION=88...."
var foo = HttpUtility.ParseQueryString(rawResponse); //NameValueCollection
var bar = foo["FIRSTNAME"]; //Joe

RESTSharp has problems deserializing XML including Byte Order Mark?

There is a public webservice which I want to use in a short C# Application:
http://ws.parlament.ch/
The returned XML from this webservice has a "BOM" at the beginning, which causes RESTSharp to fail the deserializing of the XML with the following error message:
Error retrieving response. Check inner details for more info. --->
System.Xml.XmlException: Data at the root level is invalid. Line 1,
position 1. at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg) at
System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace() at
System.Xml.XmlTextReaderImpl.ParseDocumentContent() at
System.Xml.XmlTextReaderImpl.Read() at
System.Xml.Linq.XDocument.Load(XmlReader reader, LoadOptions options)
at System.Xml.Linq.XDocument.Parse(String text, LoadOptions options)
at System.Xml.Linq.XDocument.Parse(String text) at
RestSharp.Deserializers.XmlDeserializer.Deserialize[T](IRestResponse
response) at RestSharp.RestClient.Deserialize[T](IRestRequest
request, IRestResponse raw)
--- End of inner exception stack trace ---
Here is an easy sample by using http://ws.parlament.ch/sessions?format=xml to get a List of 'Sessions':
public class Session
{
public int Id { get; set; }
public DateTime? Updated { get; set; }
public int? Code { get; set; }
public DateTime? From { get; set; }
public string Name { get; set; }
public DateTime? To { get; set; }
}
static void Main(string[] args)
{
var request = new RestRequest();
request.RequestFormat = DataFormat.Xml;
request.Resource = "sessions";
request.AddParameter("format", "xml");
var client = new RestClient("http://ws.parlament.ch/");
var response = client.Execute<List<Session>>(request);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
var ex = new ApplicationException(message, response.ErrorException);
Console.WriteLine(ex);
}
List<Session> test = response.Data;
Console.Read();
}
When I first manipulate the returned xml with Fiddler to remove the first 3 bits (the "BOM"), the above code works! May someone please help me to handle this directly in RESTSharp? What am I doing wrong? THANK YOU in advance!
I found the Solution - Thank you #arootbeer for the hints!
Instead of wrapping the XMLDeserializer, you can also use the 'RestRequest.OnBeforeDeserialization' event from #RESTSharp. So you just need to insert something like this after the new RestRequest() (see my initial code example) and then it works perfect!
request.OnBeforeDeserialization = resp =>
{
//remove the first ByteOrderMark
//see: http://stackoverflow.com/questions/19663100/restsharp-has-problems-deserializing-xml-including-byte-order-mark
string byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
if (resp.Content.StartsWith(byteOrderMarkUtf8))
resp.Content = resp.Content.Remove(0, byteOrderMarkUtf8.Length);
};
I had this same problem, but not specifically with RestSharp. Use this:
var responseXml = new UTF8Encoding(false).GetString(bytes);
Original discussion: XmlReader breaks on UTF-8 BOM
Pertinent quote from the answer:
The xml string must not (!) contain the BOM, the BOM is only allowed in byte data (e.g. streams) which is encoded with UTF-8. This is because the string representation is not encoded, but already a sequence of unicode characters.
Edit:
Looking through their docs, it looks like the most straightforward way to handle this (aside from a GitHub issue) is to call the non-generic Execute() method and deserialize the response from that string. You could also create an IDeserializer that wraps the default XML deserializer.
The solution that #dataCore posted doesn't quite work, but this one should.
request.OnBeforeDeserialization = resp => {
if (resp.RawBytes.Length >= 3 && resp.RawBytes[0] == 0xEF && resp.RawBytes[1] == 0xBB && resp.RawBytes[2] == 0xBF)
{
// Copy the data but with the UTF-8 BOM removed.
var newData = new byte[resp.RawBytes.Length - 3];
Buffer.BlockCopy(resp.RawBytes, 3, newData, 0, newData.Length);
resp.RawBytes = newData;
// Force re-conversion to string on next access
resp.Content = null;
}
};
Setting resp.Content to null is there as a safety guard, as RawBytes is only converted to a string if Content isn't already set to a value.
To make it work with RestSharp you can parse response content manually and remove all the "funny" characters coming before the '<'.
var firstChar = responseContent[0];
// removing any 'funny' characters coming before '<'
while (firstChar != 60)
{
responseContent= responseContent.Remove(0, 1);
firstChar = responseContent[0];
}
XmlReader.Create(new StringReader(responseContent));

Reading Serialized MFC CArray in C#

MFC CArray was Serialized and saved to a database. I need to read this data into a C# project. I am able to retrieve the data as byte[] from the database. I then write the byte[] to a MemoryStream. Now I need to read the data from the MemoryStream.
Someone has apparently solved this before, but did not write their solution.
http://social.msdn.microsoft.com/Forums/eu/csharpgeneral/thread/17393adc-1f1e-4e12-8975-527f42e5393e
I followed these projects in my attempt to solve the problem.
http://www.codeproject.com/Articles/32741/Implementing-MFC-Style-Serialization-in-NET-Part-1
http://www.codeproject.com/Articles/32742/Implementing-MFC-Style-Serialization-in-NET-Part-2
The first thing in the byte[] is the size of the array, and I can retrieve that with binaryReader.readInt32(). However, I cannot seem to get back the float values. If I try binaryReader.readSingle() or
public void Read(out float d) {
byte[] bytes = new byte[4];
reader.Read(bytes, m_Index, 4);
d = BitConverter.ToSingle(bytes, 0);
}
I do not get back the correct data. What am I missing?
EDIT Here is the C++ code that serializes the data
typedef CArray<float, float> FloatArray;
FloatArray floatArray;
// fill floatArray
CSharedFile memoryFile(GMEM_MOVEABLE | GMEM_ZEROINIT);
CArchive ar(&memoryFile, CArchive::store);
floatArray.Serialize(ar);
ar.Close();
EDIT 2
By reading backward, I was able to get all of the floats, and was also able to determine that the size for CArray is byte[2], or Int16. Does anyone know if this is always the case?
Using the codeproject articles above, here is a C# implementation of CArray which will allow you to deserialize a serialized MFC CArray.
// Deriving from the IMfcArchiveSerialization interface is not mandatory
public class CArray : IMfcArchiveSerialization {
public Int16 size;
public List<float> floatValues;
public CArray() {
floatValues = new List<float>();
}
virtual public void Serialize(MfcArchive ar) {
if(ar.IsStoring()) {
throw new NotImplementedException("MfcArchive can't store");
}
else {
// be sure to read in the order in which they were stored
ar.Read(out size);
for(int i = 0; i < size; i++) {
float floatValue;
ar.Read(out floatValue);
floatValues.Add(floatValue);
}
}
}
}

Can msgpack pack a user-defined object in C#, send the pack to a C++ app where it is then unpacked?

I have a C# reply server that can pack an object and send it to a requester C# client. Can I do the same thing, but with a C# reply server communicating with a C++ requester client?
Here's an example of my C# reply server:
using System;
using System.Text;
using ZMQ;
using MsgPack;
namespace zmqMpRep
{
public class Weather
{
public int zipcode;
public int temperature;
public int humidity;
}
public class zmqMpRep
{
public static void Main(string[] args)
{
Socket replier = new Socket( SocketType.REP );
replier.Bind( "tcp://127.0.0.1:9293" );
while( true ) {
Weather weather = new Weather { zipcode = 60645, temperature = 67, humidity = 50 };
CompiledPacker packer = new CompiledPacker( false );
byte[] packWeather = packer.Pack<Weather> ( weather );
string request = replier.Recv(Encoding.Unicode);
Console.WriteLine( request.ToString() );
replier.Send( packWeather );
Weather test = packer.Unpack<Weather>( packWeather );
Console.WriteLine( "The temp of zip {0} is {1}", test.zipcode, test.temperature );
}
}
}
}
Here's my C# request client:
using System;
using System.Text;
using ZMQ;
using MsgPack;
namespace zmqMpReq
{
public class Weather
{
public int zipcode;
public int temperature;
public int humidity;
}
public class zmqMpReq
{
public static void Main(string[] args)
{
CompiledPacker packer = new CompiledPacker( false );
Socket requester = new Socket( SocketType.REQ );
requester.Connect( "tcp://127.0.0.1:9293" );
string request = "Hello";
requester.Send( request, Encoding.Unicode );
byte[] reply = null;
try {
reply = requester.Recv();
}
catch( ZMQ.Exception e) {
Console.WriteLine( "Exception: {0}", e.Message );
}
Weather weather = packer.Unpack<Weather>( reply );
Console.WriteLine( "The temp of zip {0} is {1}", weather.zipcode, weather.temperature );
System.Threading.Thread.Sleep( 5000 );
}
}
}
Most programs written in any language can communicate over sockets. So a C# socket listener can listen to C++ sender. They do by exchanging a sequence of bytes (Very simplified)
What you are doing here is serializing a C# object using MsgPack in a byte array and sending it over. On the other end the same MsgPack is used to deserialize the C# object.
This will not work across programming languages unless your serializing/deserializing library supports it, which in your case MsgPack doesn't.
Take this C# class
public class Weather
{
public int zipcode;
public int temperature;
public int humidity;
}
An equivalent C++ class
class Weather
{
public:
int zipcode;
int temperature;
int humidity;
}
Depending on your OS.. sizeof(int) in C++ will be 4 bytes(chars). sizeof(int) in C# is 4 bytes as well.
So it theory you can exchange 12 ( 4 * 3 ) bytes over a socket connection between a C++ and C# program so that weather object is pretty much the same on both sides
In C++ you should use the MSGPACK_DEFINE macro because you are dealing with a user-defines class. It is all explained in the C++ quickstart on the MSGPACK website.
In order for this to work you have to make sure that the types of each attribute in your object corresponds across languages. This is exactly what MSGPACK was intended to do and I have used it myself to write an SQLITE server based on ZeroMQ messages containing a MSGPACK object payload. Originally I was using a JSON object for the message bodies but then I wanted to send one attribute in gzipped form and it was easier to swap in MSGPACK than try to deal with binary data in a JSON string.
You might want to read http://wiki.msgpack.org/display/MSGPACK/Design+of+Serialization to understand how it works. Conceptually it is like converting 000A00130002 into "10,19,2" and back again. Of course, MSGPACK doesn't use strings as the serialization format but instead uses a very efficient binary format that is language independent.

Categories

Resources