Closed MrGibbage closed 12 years ago
There's no wonder you are having issues deserializing it, the JSON you pasted is invalid.
You can't escape the quotes like that. Your error is probobly on the side where you serialize your objects. The CometD library already serialize/deserialize JSON so you shouldn't have to...
Yeah, that was definitely wrong. I had been trying several different things and that was just the latest try.
Here's how I serialize:
System.Web.Script.Serialization.JavaScriptSerializer oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); String serNotificationTypes = oSerializer.Serialize(notificationTypes); // a List of instances of the NotificationTypes class String serApplication = oSerializer.Serialize(application); // an instance of the Application class String serRequestInfo = oSerializer.Serialize(requestInfo); // an instnace of the requestInfo class Dictionary<String, Object> d = new Dictionary<String, Object>(); d.Add("Encrypted", "true"); d.Add("MessageType", "Registration"); d.Add("NotificationTypes", serNotificationTypes); d.Add("Application", serApplication); d.Add("RequestInfo", serRequestInfo); my_channel.publish(d);
Then, to deserialize, I have been trying different things.
public static void PrepareGrowlRegistration(IMessage message)
{
dataDict = message.DataAsDictionary;
System.Web.Script.Serialization.JavaScriptSerializer oSerializer =
new System.Web.Script.Serialization.JavaScriptSerializer();
MyGrowlApplication mga = new MyGrowlApplication();
try
{
String app = dataDict["Application"].ToString();
System.IO.File.WriteAllText(@"C:\temp\WriteText.txt", app);
mga = oSerializer.Deserialize
The received JSON for "Application" looks this:
{ "Name":"growlnotify", "Icon": { "Url":null, "Data":null, "IsSet":false, "IsRawData":false, "IsUrl":false }, "MachineName":"ANARKI", "SoftwareName":"GrowlConnector", "SoftwareVersion":"1.0.0.0", "PlatformName":"Microsoft Windows NT 6.1.7601 Service Pack 1", "PlatformVersion":"6.1.7601.65536", "CustomTextAttributes":{}, "CustomBinaryAttributes":{} }
So it looks like I am getting closer, but I still have not cracked the code. Right now I am stuck on the lack of a paramaterless constructor for Strings
Any ideas?
Why are you trying to deserialize it? It is already deserialized into a Dictionary by the library?
LOL, because I don't know what I am doing :)
So, if I have that dictionary, with that JSON as I put in my last post for the "Application", then how will I get access to the individual elements: "Name", "Icon", "MachineName", etc.
And how are Icon, CustomTextAtrributes and CustomBinaryAttributes handled, since they are "JSON within a JSON"??? In other words, how will I access the Icon.Url?
If you haven't figured it out yet, I am kinda new at this, so go easy on me :) But, seriously, thanks for your help :)
You shouldn't think of the data as "JSON" at all since that's only the way it's transported. The way to work with this data is more of a generic C# question than about using cometd, but here's an probably ok reference to understand how to work with dictionaries in C#:
Sorry, that isn't where I am having trouble. I get the dictionary concept (quite well, actually). This is just a dictionary with String keys and objects as the value. The object is really just a String that looks a lot like JSON. You suggest to not think of it as JSON, in which case, I don't know how I would access the individual elements that are stored in that string. In this case, the Application key of the dictionary contains
{ "Name":"growlnotify", "Icon": { "Url":null, "Data":null, "IsSet":false, "IsRawData":false, "IsUrl":false }, "MachineName":"ANARKI", "SoftwareName":"GrowlConnector", "SoftwareVersion":"1.0.0.0", "PlatformName":"Microsoft Windows NT 6.1.7601 Service Pack 1", "PlatformVersion":"6.1.7601.65536", "CustomTextAttributes":{}, "CustomBinaryAttributes":{} }
I don't know how I would access any of the named elements in that string, such as the Name, Icon, and MachineName.
I totally get that this is no longer a CometD.Net question, but I was hoping that since it is directly related to the use of CometD, that maybe I could still get some help here.
By the way, I have read up on JSON serializers and deserializers and they are usually implemented as
//serialize MyClass c = new MyClass(); System.Web.Script.Serialization.JavaScriptSerializer oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); string sJSON = oSerializer.Serialize(c);
//deserialize
MyClass mc = oSerializer.Deserialize
So, I really thought I would be able to do the same here. If I can't, that's fine. I'm just trying to learn how this all works. In my case, I add the sJSON to the data dictionary along with some other serialized data. Then, when I retrieve it, I would just deserialize it and be good to go with a new instance of that class. Am I missing something?
Are you developing both the client and the server in your case?
What is the data-type on the value of dataDict["Application"]
? Isn't that itself also a Dictionary, and as such you would access it as dataDict["Application"]["Name"]
?
dataDict is declared as IDictionary<String, object> dataDict;
I've been casting them to string and trying to feed them into the deserializer, but that hasn't been working. I don't think there is any way to access Name like that. In this case, dataDict["Application"] is an object, in this case, a string equal to
{ "Name":"growlnotify", "Icon": { "Url":null, "Data":null, "IsSet":false, "IsRawData":false, "IsUrl":false }, "MachineName":"ANARKI", "SoftwareName":"GrowlConnector", "SoftwareVersion":"1.0.0.0", "PlatformName":"Microsoft Windows NT 6.1.7601 Service Pack 1", "PlatformVersion":"6.1.7601.65536", "CustomTextAttributes":{}, "CustomBinaryAttributes":{} }
Yeah, it looks like a dictionary (with a lower-case "d"), but it is not a Dictionary<T,T> class.
To confirm, I just tried it and I get a compiler error:
public static void PrepareGrowlRegistration(Cometd.Bayeux.IMessage message) { IDictionary<String, object> dataDict; dataDict = message.DataAsDictionary; String name = dataDict["Application"]["Name"]; // error: Cannot apply indexing with [] to an expression of type 'object'
Anyway, to answer your first question, yes, I am writing both the server and client. I have the bayeux cometd server running on my web server. I have one sender client that sends notifications to the server and I have a different client that long polls and waits for notifications to come in. I believe the sender side is working OK, as I am getting valid JSON incoming into the IMessage, which is further converted to a dictionary through the message.dataAsDictionary. My problem is (what I think is known as) deserialization. Even if I can't directly deserialize directly back into the original class type, I will be happy with directly accessing the elements within the JSON message and using those values to construct a new instance of that class. The problem is, I don't know how to do that either.
I guess at its simplest, my question is, what can I do with the IMessage once it is received? Especially if the data payload contains serialized instances of some classes. I guess that since this IMessage is a Cometd.Bayeux namespace, I should ask on the CometD forums?
This isn't an topic for the Cometd guys, this is about serialization and C#. I suggest you take a look at our own code example on how we interpret messages received from the Cometd channels here:
https://github.com/Oyatel/oyatel-api-examples/tree/master/csharp/Oyatel.Connect.Tutorial
See first StreamingEvents.cs, line 107-118, then take a look at DemoForm.cs, line 94 - 137.
That helps. A little. What I think is going wrong is I am using the data dictionary to store serialized representations of objects when it was really intended to hold simpler key-value pairs. I just need help with Serialization/deserialization. You are right, this is not a question for the Cometd guys, but maybe it would be better on StackOverflow as a general question about serialization (as you suggested).
Do you have any OnCallEvent(IDictionary) code samples?
The code sample is already there if you took a look at the codelines I mentioned in the last comment...
I am using System.Web.Script.Serialization.JavaScriptSerialize to serialize and deserialize my messages. I am having trouble deserializing the messages. Here is a sample message:
{ "id":"3072", "data": { "Application": "{ \"Name\":\"growlnotify\", \"Icon\": { \"Url\":null, \"Data\":null, \"IsSet\":false, \"IsRawData\":false, \"IsUrl\":false }, \"MachineName\":\"ANARKI\", \"SoftwareName\":\"GrowlConnector\", \"SoftwareVersion\":\"1.0.0.0\", \"PlatformName\": \"Microsoft Windows NT 6.1.7601 Service Pack 1\", \"PlatformVersion\":\"6.1.7601.65536\", \"CustomTextAttributes\":{}, \"CustomBinaryAttributes\":{} }", "Encrypted":"true", "RequestInfo":" { \"ReceivedFrom\":\"127.0.0.1\", \"ReceivedBy\":\"ANARKI (86c9ad7e-6894-471f-b8cd-141601c3afa9)\", \"ReceivedWith\":\"Growl/Win\", \"TimeReceived\":\"\/Date(1327489554253)\/\", \"RequestID\":\"4ec3df33-ec08-4759-9ec3-da3e1c4824d8\", \"PreviousReceivedHeaders\":[], \"HandlingInfo\": [ \"Notification Origin: 127.0.0.1 [LOCAL MACHINE]\", \"Forwarding to http://pelorus.org:8080/cometd (skip@pelorus.org)\" ] }", "NotificationTypes":" [ { \"Name\":\"General Notification\", \"DisplayName\":\"General Notification\", \"Icon\": { \"Url\":null, \"Data\":null, \"IsSet\":false, \"IsRawData\":false, \"IsUrl\":false }, \"Enabled\":true, \"MachineName\":\"ANARKI\", \"SoftwareName\":\"Growl/Win\", \"SoftwareVersion\":\"2.0.8.1\", \"PlatformName\":\"Microsoft Windows NT 6.1.7601 Service Pack 1\", \"PlatformVersion\":\"6.1.7601.65536\", \"CustomTextAttributes\":{}, \"CustomBinaryAttributes\":{} } ]", "MessageType":"Registration" }, "channel":"/chat/skip@pelorus.org" }
What methods are people here using to deserialize their JSON objects? Anyone have any sample code I could look at?