2010-10-22 6 views
2

У меня есть данные в следующей форме:Более элегантный способ десериализации Json с LINQ?

{ 
    "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.

ответ

0

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

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

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

_sections.AddRange(sections); 

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

_sections = sections.ToList(); 
2

Что-то вдоль линий ...

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

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

+0

.. или, может быть, мне не хватает точки, кажется, что формат данных отвечает за то, что вы не просто сделали это простым способом? –

+0

есть небольшие несоответствия между форматом данных и моими классами. –

0

Я предлагаю вам переписывать анонимный делегат в 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 доступна в делегат передается Выбрать. Этот подход должен избавиться от цикла foreach.

+0

Это не работает. Я подозреваю, что это связано с тем, что в запросе было поставлено '_sections.Add (section)'. Запрос не выполняется до тех пор, пока он не будет повторен, правильно? Поэтому в этом случае вам все равно нужно ударить все результаты запроса, чтобы он запускался. –