PubNub JSON serialization code works in example project but not in my project

1.4k Views Asked by At

I am making a Winamp plugin with the single function of sending the details of the song being played over HTTP to a webpage.

It works like this: Winamp song event triggered -> check for new song -> publish to webpage using PubNub (C# API).

So far I got to the stage where everything works exactly as it is supposed to, except for the PubNub code which doesn't serialize the object I'm passing for publishing into JSON. All I keep getting in the PubNub console is a mere {} - an empty JSON object.

A little background on the project structure:

Project breakdown

I am using Sharpamp which is a custom library that enables making Winamp plugins with C#. I am also using the PubNub C# API. The gen_notifier_cs project is the C++ plugin wrapper created by Sharpamp. notifier_cs is where all my code resides. The two other projects are self explanatory I assume. I have referenced the PubNub API in notifier_cs, and also have referenced Sharpamp in both notifier_cs and PubNub API.

So, the objects that need to get serialized are of a class Song as defined in Sharpamp:

    public class Song
{
    public string Title { get; internal set; }
    public string Artist { get; internal set; }
    public string Album { get; internal set; }
    public string Year { get; internal set; }
    public bool HasMetadata { get; internal set; }
    public string Filename { get; internal set; }
}

So let's say if I have a song object with song data in it, I would go pubnub.publish("winamp_pipe", song); to publish it and PubNub will automatically serialize the data into JSON. But that's just not working in my solution.

To test why it wasn't serializing, I copied that class to the example code file in the PubNub API. Visual Studio changed the class to this (notice the public Song() method):

public class Song
{
    public Song() // VS added this method
    {
        return; // I added this otherwise it would not compile
    }

    public string Album { get; set; }
    public string Artist { get; set; }
    public string Filename { get; set; }
    public bool HasMetadata { get; set; }
    public string Title { get; set; }
    public string Year { get; set; }
}

On the same example file I initiated a default song object with some values:

Song song = new Song();
song.Album = "albumname";
song.Artist = "artistname";
song.HasMetadata = true;
song.Title = "songtitle";
song.Year = "2012";

And published it: pubnub.publish("winamp_pipe", song); and it worked! I got the JSON object in the PubNub channel!

{"Album":"albumname","Artist":"artistname","Filename":null,"HasMetadata":true,"Title":"songtitle","Year":"2012"}

So, I tried replacing the "new" Song class with the original one defined in Sharpamp. I tried adding another class definition in the notifier_cs project but that clashes with the one in Sharpamp which I have to rely on. I have been trying so many things as far as I could come up with. Needless to say none prevailed. Still, all I get is an empty JSON object.

This is the code that does the serializing, within the publish method in the PubNub API. I will remind you this code works with the PubNub example files but not with my project:

DataContractJsonSerializer serializer = new DataContractJsonSerializer(objectToSerialize.GetType());
serializer.WriteObject(ms, objectToSerialize);
ms.Position = 0;
using (StreamReader reader = new StreamReader(ms))
{
    return reader.ReadToEnd();
}

I have been pulling out my hair for the last day. I know this post is super long but I appreciate your input nonetheless.

2

There are 2 best solutions below

2
On

Publishing Data: PubNub and C# Winamp Song Class

You already have the data stored in a winamp_song object instance. If you attempt to serialize the winamp_song object instance, it will fail. The serialization will fail if you pass in the winamp_song as the instance has non-serializable members. The best way to proceed is for you to create a Song class that you own and define. Define the member values in the Song class which will be delivered via PubNub. This way you can populate directly the values that are needed to publish to your subscribers.

Song song = new Song();
song.Album = winamp_song.Album;
song.Artist = winamp_song.Artis;
song.HasMetadata = winamp_song.HasMetadata;
song.Title = winamp_song.Title;
song.Year = winamp_song.Year;

When you receive the Song data publish even on your subscriber, you will be able to receive deserialized data, populating the values into a new Song class instance.

Song Class Defined Below

public class Song {
    public Song() { return; }
    public string Album { get; set; }
    public string Artist { get; set; }
    public string Filename { get; set; }
    public bool HasMetadata { get; set; }
    public string Title { get; set; }
    public string Year { get; set; }
}

PubNub is the best method for communicating with installed copies of your Winamp plugin.

1
On

Well, my "solution", since I am only using one class (the Song class, defined in the Sharpamp library) to publish values by, is manually constructing a JSON string:

pubnub.publish("winamp_pipe", "{\"Album\": \""+song.Album+"\",\"Artist\": \""+song.Artist+"\",\"HasMetadata\": \""+song.HasMetadata.ToString()+"\",\"Title\": \""+song.Title+"\",\"Year\": \""+song.Year+"\",\"Filename\": \""+song.Filename+"\"}");

It is not a solution to the problem itself but it serves the purpose of publishing the information as a JSON object (as long as you don't have any special characters that break the JSON structure in your data).

I am not marking this as an answer because it is not a solution to the real problem, only a temporary workaround...