Более элегантный способ десериализации Json с помощью LINQ? - PullRequest
2 голосов
/ 22 октября 2010

У меня есть данные следующей формы:

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

Я хотел бы сериализовать его в коллекцию следующего класса:

public class Section
{

    public string Name;
    public int Tid;
}

Вот код, который я использую для этого, используя 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);
        }

Это кажется немного неуклюжим. Могу ли я сделать это более элегантно?

Особенно этот foreach цикл в конце. Я бы предпочел использовать такой метод, как addAll или concat или что-то еще.

Ответы [ 3 ]

2 голосов
/ 22 октября 2010

Нечто подобное ...

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

Также обратите внимание на DataContractJsonSerializer, который технически заменяет JavaScriptSerializer, но всегда кажется трудным, когда я пытаюсь его использовать.

0 голосов
/ 22 октября 2010

Я предлагаю переписать анонимного делегата в операторе Select следующим образом:

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;
    });

Помните, что лямбды могут образовывать замыкания, поэтому коллекция _sections доступна в делегате, переданном в Select. Этот подход должен избавиться от цикла foreach.

0 голосов
/ 22 октября 2010

Вам не нужно использовать Replace для удаления разделителя тысяч перед анализом числа, метод Parse способен обработать их, если вы просто разрешите их и убедитесь, что он использует культуру, которая на самом деле имеет запятые в качестве разделителя тысяч:

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

Если переменная _sections является List<Section>, то вы можете просто использовать ее метод AddRange, чтобы добавить их все сразу:

_sections.AddRange(sections);

В качестве альтернативы, если список должен содержать только эти элементы, вы можете создать список из результата, а не создавать его сначала, а затем добавлять к нему элементы:

_sections = sections.ToList();
...