tags:

views:

434

answers:

3

Hi, My code is below. I am not able to extract the 'name' and 'query' lists from the JSON via a DataContracted Class (below) I have spent a long time trying to work this one out, and could really do with some help...

My Json string:

{"as_of":1266853488,"trends":{"2010-02-22 
15:44:48":[{"name":"#nowplaying","query":"#nowplaying"},{"name":"#musicmonday","query":"#musicmonday"},{"name":"#WeGoTogetherLike","query":"#WeGoTogetherLike"},{"name":"#imcurious","query":"#imcurious"},{"name":"#mm","query":"#mm"},{"name":"#HumanoidCityTour","query":"#HumanoidCityTour"},{"name":"#awesomeindianthings","query":"#awesomeindianthings"},{"name":"#officeformac","query":"#officeformac"},{"name":"Justin 
Bieber","query":"\"Justin Bieber\""},{"name":"National 
Margarita","query":"\"National Margarita\""}]}}

My code:

WebClient wc = new WebClient();
wc.Credentials = new NetworkCredential(this.Auth.UserName, this.Auth.Password);
string res = wc.DownloadString(new Uri(link));
//the download string gives me the above JSON string - no problems
Trends trends = new Trends();
Trends obj = Deserialise<Trends>(res);


private T Deserialise<T>(string json)
{
    T obj = Activator.CreateInstance<T>();
    using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
    {
        DataContractJsonSerializer serialiser = new DataContractJsonSerializer(obj.GetType());
        obj = (T)serialiser.ReadObject(ms);
        ms.Close();
        return obj;
    }
}


[DataContract]
public class Trends 
{
    [DataMember(Name = "as_of")]
    public string AsOf { get; set; }

    //The As_OF value is returned - But how do I get the 
    //multidimensional array of Names and Queries from the JSON here?
} 
A: 

Consider this example:

public struct TwitterResponse
{
  public int32 as_of;
  public Trend[] Trends;
}

public struct Trends
{
  public String name;
  public String query;
}

Trend[] obj = JavaScriptConvert.DeserializeObject<TwitterResponse>( res ).Trends;

Probably needs finetuning, but that's the general idea on how to do it.

Theofanis Pantelides
I tried this but still not the answer, thanks
James
+2  A: 

have you considered using JSON.net ?

AndreasKnudsen
Hi, This does not answer the question. I am looking for how to do this in C#. I am not asking where to download a third party dll. Thanks all the same.
James
That is how to do this in C#. You mean how to do this in only the .Net Framework.
sixlettervariables
(-1) You haven't (in *any* way) indicated why this is better, how to use this, what the OP should do if they come across the same problem again. Additionally, suggesting that someone completely start over on something without any knowledge of the project isn't usually fruitful.
I'm sorry you found the answer offensive, but rolling your own JSON parsing when perfectly good frameworks exist which do the same seems like a lot of work for nothing. If James didn't know of JSON.net when he asked the question and had painted himself into a corner with custom code it might have been helpful to him. As it stands his reply to this answer was that he WANTED to roll his own in C#, in which case my reply would be "good luck to you sir". (unfortunately as I am not a Psychic I could not know that at the time of my reply)
AndreasKnudsen
+2  A: 

I've run into this very issue while developing Twitterizer. The issue is that the dataset isn't in a traditional object-oriented design.

If you were to map that as objects, you would see:

object root
  int as_of
  object trends
    array[object] <date value of as_of>
      string query
      string name

As you can see, the trend object has a property that's name changes. The name is based on the as_of date value. As such, it can't be automatically deserialized.

My first solution was to use System.Web.Script.Serialization.JavaScriptSerializer.DeserializeObject(). That method returns a hierarchy of weakly typed, nested dictionary instances. I then stepped through the results myself.

internal static TwitterTrendTimeframe ConvertWeakTrend(object value)
{
    Dictionary<string, object> valueDictionary = (Dictionary<string, object>)value;
    DateTime date = new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds((int)valueDictionary["as_of"]);
    object[] trends = (object[])((Dictionary<string, object>)valueDictionary["trends"])[date.ToString("yyyy-MM-dd HH:mm:ss")];

    TwitterTrendTimeframe convertedResult = new TwitterTrendTimeframe()
    {
        EffectiveDate = date,
        Trends = new Collection<TwitterTrend>()
    };

    for (int i = 0; i < trends.Length; i++)
    {
        Dictionary<string, object> item = (Dictionary<string, object>)trends[i];

        TwitterTrend trend = new TwitterTrend()
        {
            Name = (string)item["name"]
        };

        if (item.ContainsKey("url"))
        {
            trend.Address = (string)item["url"];
        }

        if (item.ContainsKey("query"))
        {
            trend.SearchQuery = (string)item["query"];
        }

        convertedResult.Trends.Add(trend);
    }

    return convertedResult;
}

It's ugly, but it worked.

I've since embraced the use of Json.NET for it's speed and simplicity.

Ricky Smith