views:

72

answers:

3

I have data of the following form:

{
  "sections" : [
    {
      "section" : {
        "Term" : "News",
        "Term ID" : "4,253"
      }
    },
    {
      "section" : {
        "Term" : "Sports",
        "Term ID" : "4,254"
      }
    },
   // ...
  ]
}

I would like to serialize it into a collection of the following class:

public class Section
{

    public string Name;
    public int Tid;
}

Here is the code I'm using to do it, using JSON.NET:

        // e.Result is the downloaded JSON
        JObject jsonData = JObject.Parse(e.Result);
        var sections = jsonData["sections"].Select(obj => obj["section"]).Select(sectData => new Section()
        {
            Name = HttpUtility.HtmlDecode(sectData["Term"].Value<string>().Replace("\"", "")),
            Tid = int.Parse(sectData["Term ID"].Value<string>().Replace(",", ""))
        });

        foreach (Section s in sections)
        {
            // _sections is an ObservableCollection<Section>
            _sections.Add(s);
        }

It feels a bit clunky. Can I do this more elegantly?

Particularly that foreach loop at the end. I'd rather use a method like addAll or concat or something.

A: 

You don't have to use Replace to remove the thousand separator before parsing the number, the Parse method is capable of handling them if you just allow them and make sure that it uses a culture that actually has commas as thousands separator:

Tid = Int32.Parse(sectData["Term ID"].Value<string>(), NumberStyles.AllowThousands, CultureInfo.InvariantCulture)

If the _sections variable is a List<Section>, then you can just use it's AddRange method to add them all at once:

_sections.AddRange(sections);

Alternatively, if the list is to only contain those items, you can create the list from the result instead of creating it first and then adding the items to it:

_sections = sections.ToList();
Guffa
+1  A: 

Something along the lines of...

JavaScriptSerializer serializer = new JavaScriptSerializer();
List<Section> sections = serializer.Deserialize<List<Sections>>(e.Result);

Also look at DataContractJsonSerializer which technically supercedes JavaScriptSerializer but it always seems to be a hassle when I try to use it.

jamietre
.. or maybe i'm missing the point, it seems that the data format is responsible for your not simple doing it the easy way?
jamietre
there are slight inconsistencies between the data format and my classes.
Rosarch
A: 

I suggest that you rewrite the anonymous delegate in the Select statement as follows:

var sections = jsonData["sections"].Select(obj => obj["section"]).Select(sectData =>
    {
        var section = new Section()
        {
            Name = HttpUtility.HtmlDecode(sectData["Term"].Value<string>().Replace("\"", `enter code here`"")),
            Tid = int.Parse(sectData["Term ID"].Value<string>().Replace(",", ""))
        };
        _sections.Add(section);
        return section;
    });

Remember that lambdas can form closures, so the _sections collection is available in the delegate passed to Select. This approach should get rid of the foreach loop.

Genady Sergeev
This doesn't work. I suspect it is because of putting `_sections.Add(section)` in the query. The query isn't executed until it is iterated over, right? So in this case you still need to hit all the results in the query to make it run.
Rosarch