In on_message() method of SockJS-Tornado library, I want to send JSON messages to clients: sometimes to specific clients using send() method, and sometimes to a group of clients using broadcast() method.
I wonder whether I need to use something like simplejson to encode string-keyed dictionary object myself before sending the message, i.e.
on_message(self, message):
...
data = {'type': 1, 'body': 'blah'}
msg = json.dump(data)
# self.send(msg) or self.broadcast(conns, msg)
Or the encoding part is already taken care of by SockJS-Tornado? In addition, is it true that message argument in on_message() method is always also a JSON object?
SockJS is websocket emulation layer. Websockets don't support anything except of text and binary data.
So, while you can send arbitrary python object over the wire (sockjs-tornado will do internal json serialization and does not enforce strings), this is discouraged for compatibility reasons.
Yes, double encoding will happen if json is used as a application protocol. However, if you're going to have broadcast functionality - use optimized broadcast() method, it will do json-encoding only once for all recipients.
There was related discussion in mailing list as well: https://groups.google.com/forum/?fromgroups#!topic/sockjs/vsFvHqppq5g
Related
I'm building a microservice system with multiple disconnected components, and I'm currently trying to find out how to implement knowing which fields on an object should be updated based on the protobuf data provided.
The flow is this:
The client sends a JSON-request to an API.
The API translates the JSON-data into a protobuf struct, which is then sent along to the microservice responsible for handling it.
The microservice receives the data from the API and performs any action on it, in this case, I'm trying to change a single value in a MySQL table, such as a client's email address.
Now, the problem I have is that since protobuf (understandably) doesn't allow pointers, the protobuf object will contain zero-values for everything not provided. This means that if a customer wants to update their email address, I can't know if they also set IncludeInMailLists to false - or if it was simply not provided (having its zero-value) and shouldn't change.
The question is: how will I - from the protobuf object - know if a value is expressively set to 0, or just not provided?
My current solution is pretty much having a special UpdateCustomer-object which also has an array of Fields specifying which fields the microservice should care about, but it feels like bad solution.
Someone must have solved this better already. How should I implement it?
Protobufs field masks are one way.
https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.FieldMask
https://github.com/golang/protobuf/issues/225
But if you are using grpc then there's a (sort of) built in way.
Grpc wrappers
Since proto3 (protobufs v3) there's been no distinction between a primitive that is not set, and a primitive that's been set to the "zero value" (false, 0, "", etc).
Instead you can use objects or in protobufs language a "message", as objects can be nil / null. You've not mentioned what language you are working in but hopefully these examples make sense.
Given an RPC service such as:
import "google/protobuf/wrappers.proto";
service Users {
rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse)
}
message UpdateUserRequest {
int32 user_id = 1;
google.protobuf.StringValue email = 2;
}
message UpdateUserResponse {}
Note the import "google/protobuf/wrappers.proto"; is important.
It given you access to the google protobufs wrappers source code here. These are not objects that have methods that allow you to test for presence.
Grpc generated code in java gives you methods such as .hasEmail() which returns true if the value is present. The getter on an unset value will still return you the zero value. I think the golang version uses pointers that you can test for nil instead of an explicit hasX() method.
More info / discussion in this github issue
I know there is a way to serialize a message in protobuf. But is there a easy way to print out the values in a protobuf message? Something like a toString() method in Java?
Thanks.
protocol buffer basics -- Java
quoted from the link, check the standard message methods:
Standard Message Methods
Each message and builder class also contains a number of other methods that let you check or manipulate the entire message, including:
isInitialized(): checks if all the required fields have been set.
toString(): returns a human-readable representation of the message, particularly useful for debugging.
mergeFrom(Message other): (builder only) merges the contents of other into this message, overwriting singular fields and concatenating repeated ones.
clear(): (builder only) clears all the fields back to the empty state.
I have a mirth instance (version 3.0.1) sending out using a POST method to a web api restfull service.
[POST("MessagesHl7/OML_O21")] public HttpResponseMessage
PostOmlo21([FromBody] sting receivedmessage) {..}
The problem is that the message hl7 that is sent to the service
in a outbound message is cut in the first characters. For example, in the message:
MSH|^~\&|CPSI^1.3.6.1.4.1.27248.1.17^ ISO|CGH|...
in the receivedmessage variable the text MSH|^~\ is received only.
How can I do in order that the message is not cut?
In the http channel, the configuration is:POST, not query parameters,
in
headers content-type application/x-www-form-urlencoded,
Content-Type value application/xml,
and the value that send is =${message.encodedData}.
Change your action method to not use binding and just read the request body as string.
[POST("MessagesHl7/OML_O21")]
public Task<HttpResponseMessage> PostOmlo21()
{
string receivedMessage = await Request.Content.ReadAsStringAsync();
}
I would suggest to use Base64 encoding for the HL7 piped message since
there are many special characters within the message which can be interpreted
in the wrong way during parsing. Especially during the parsing of xml.
Of course you have to decode the HL7 message on Server side.
But i think Mirth gives you all functionallity to do that.
I don't know which class to use in C#/ASP in Java appropriate classes and frameworks for
encoding an decoding Base64 exist. I believe the same is true for C# and ASP.
I have an $.ajax request that's sending the data in a serialize() and gets a json array in return. It works perfectly without any issues on Chrome develop's tools and Firefox's firebug. My question is, do I HAVE to send the data(user inputs) as json? I need json for the response but not for the request.
No, you send the data however you like but keep in mind how you send it will affect how you can retrieve it.
Also you aren't sending JSON in your request as .serialize() does not return JSON it returns a text string in standard URL-encoded notation.
No, you don't need to send it as JSON. You can send it in any other format, but your receiver will need to know how to interpret it. Usually people use JSON or XML since your receiver can easily parse these types of data.
You'll need to set the content-type, then you can tell the receiver how to process this content-type.
I'm calling a REST API somebody else created. It supports JSONP to facilitate cross domain access.
The response I get back from the service looks like:
mycallback('{"token": "123456789"}');
Notice the single quotes wrapping the JSON data; Passing it as a string rather than a raw object. JQuery can handle this, but other libraries seem to expect a raw object instead.
mycallback({"token": "123456789"});
The raw object parameter makes more sense to me since it avoids the need to parse the JSON data, but I want to know for sure before asking the maintainer of the API to make the adjustment:
Which is most correct?
Passing a javascript literal (second) as shown here is more correct as it avoids deserializing the string back to a javascript object.
Passing a string is obviously a bad thing - you have two choices (#1 is preferred):
Ask the developer of the JSONP service to send proper JSONp instead of a string
Make your callback function smart so it uses something like payload = JSON.parse(payload); in case payload is a string.