I am trying to convert a value from a CSV file using CsvHelper. The value itself is an integer but the value inside the csv contains a whitespace e.g. "0 " or "12 ".
How can I get it to work now? On StackOverFlow I found this thread but the trimming doesn't apply to the binding. According to a comment from the creator of this library it should since V2.9.0.
How do you ignore Whitespace when using CsvHelper, CsvReader.Read()?
I try to read my CSV in this way:
using (TextReader reader = new StreamReader(datei))
{
CsvConfiguration configuration = new CsvConfiguration(CultureInfo.GetCultureInfo("de-DE"));
configuration.BadDataFound = null;
configuration.TrimOptions = TrimOptions.Trim;
using (var csv = new CsvReader(reader, configuration))
{
ArtikeldatenLieferant = csv.GetRecords<AllnetArtikel>().ToList();
}
}
Edit:
This is one line of my CSV which results in this issue:
Nr.;ALLNET-Artikelnummer;Hersteller-Artikelnummer;Hersteller;Produktbezeichnung;EAN Nummer;Kategorieebene1;Kategorieebene2;Kategorieebene3;HEK;Artikelzustand;UVP;Produktbeschreibung;Gewicht;Lagerbestand
9234;193301;AL-MSUC-SUF-S;Audiocodes Live;Audiocodes Live - AL-MSUC-SUF-S;;Telekommunikation;Voice over IP;Voice over IP - Gateway Support;2739,13;neu;3043,48;"AudioCodes Live non-recurring setup fee, for each customer site with up to 500 users. Includes delivery, Planning and Design consulting service, Implementation service (configuration and basic verification) for AudioCodes hardware or software, and cutover support into production for a single event. Does not include Project Management.;0,001;0
Edit2: Here is the AllnetArtikel class.
public class AllnetArtikel
{
[Name("Nr.")]
public string Nr { get; set; } = string.Empty;
[Name("ALLNET-Artikelnummer")]
public string AllnetArtiNr{ get; set; } = string.Empty;
[Name("Hersteller-Artikelnummer")]
public string HerstellerArtiNr{ get; set; } = string.Empty;
[Name("Hersteller")]
public string Hersteller{ get; set; } = string.Empty;
[Name("Produktbezeichnung")]
public string Produktbezeichnung{ get; set; } = string.Empty;
[Name("EAN Nummer")]
public string EAN{ get; set; } = string.Empty;
[Name("Kategorieebene1")]
public string Kategorie1{ get; set; } = string.Empty;
[Name("Kategorieebene2")]
public string Kategorie2{ get; set; } = string.Empty;
[Name("Kategorieebene3")]
public string Kategorie3{ get; set; } = string.Empty;
[Name("HEK")]
public decimal HEK{ get; set; }
[Name("Artikelzustand")]
public string Zustand{ get; set; } = string.Empty;
[Name("UVP")]
public decimal UVP{ get; set; }
[Name("Produktbeschreibung")]
public string Produktbeschreibung{ get; set; } = string.Empty;
[Name("Gewicht")]
[Default(-1)]
public decimal Gewicht{ get; set; }
[Name("Lagerbestand")]
public int Lagerbestand { get; set; }
}
Final Update
The issue ended up being a quote in a field and the quote was not escaped or the field contained in quotes. ;"AudioCodes ... Management.;. Since the quote was a part of the data that was needed, the solution was to change the configuration mode to NoEscape. This mode will ignore quotes and escape characters.
configuration.Mode = CsvMode.NoEscape;
Update
Any string that works with int.Parse should work with CsvHelper. For instance int.Parse("0 ") == 0. Since having extra whitespace is not an issue and it works when you change your integer field to string, I'm going to take a guess that your issue is actually with an empty value. CsvHelper is unable to convert any empty values into an int. If that is the case, you have two choices.
Either turn your integer field into a Nullable<int>
void Main()
{
CsvConfiguration configuration = new CsvConfiguration(CultureInfo.GetCultureInfo("de-DE"));
using (var reader = new StringReader("Id;Name\n1;Joe\n;Jenny"))
using (var csv = new CsvReader(reader, configuration))
{
var records = csv.GetRecords<Foo>().ToList().Dump();
}
}
public class Foo
{
public int? Id { get; set; }
public string Name { get; set; }
}
Or give your integer field a default value.
void Main()
{
CsvConfiguration configuration = new CsvConfiguration(CultureInfo.GetCultureInfo("de-DE"));
using (var reader = new StringReader("Id;Name\n1;Joe\n;Jenny"))
using (var csv = new CsvReader(reader, configuration))
{
var records = csv.GetRecords<Foo>().ToList().Dump();
}
}
public class Foo
{
[Default(0)]
public int Id { get; set; }
public string Name { get; set; }
}
Original
Are you sure you aren't getting an exception for something else? I can put in as many spaces after the number as I want and it still reads it correctly.
void Main()
{
CsvConfiguration configuration = new CsvConfiguration(CultureInfo.GetCultureInfo("de-DE"));
using (var reader = new StringReader("Id;Name\n1 ;Joe\n10 ;Jenny"))
using (var csv = new CsvReader(reader, configuration))
{
var records = csv.GetRecords<Foo>().ToList();
}
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
The JSON data is as follows:
{"Sucess":true,
"Code":0,
"Msg":"Sucess",
"Data":{
"UserDayRanking":
{
"UserID":11452112,
"UserCharm":0,
"UserName":"gay",
"UserGender":1,
"UserLevel":36,
"UserPhoto":"http://res.xxx.com/2020/3/16/63719926625601201487545U11452112.jpeg",
"Ranking":0,
"IsNobility":0,
"NobilityType":0,
"NobilityLevel":0,
"UserShowStyle":null,
"LiveLevelUrl":null,
"IsStealth":false},
"DayRankingList":[
{
"UserID":3974854,
"UserCharm":114858,
"UserName":"jack",
"UserGender":1,
"UserLevel":91,
"UserPhoto":"http://res.xxx.com/2020/2/15/63717400601924412312384U3974854.jpeg",
"Ranking":2,
"IsNobility":1,
"NobilityType":1,
"NobilityLevel":3,
"UserShowStyle":
{
"NameColor":100102,
"BorderColor":100403,
"LiangMedal":0,
"DztCountDown":0,
"Mounts":100204,
"LiveLevelCode":0,
"LiveRights":null
},
"LiveLevelUrl":null,
"IsStealth":false
},
{"UserID":6231512,
"UserCharm":22644,
"UserName":"red.girl",
"UserGender":1,
"UserLevel":57,
"UserPhoto":"http://res.xxx.com/2019/11/20/63709843050801519858823U6231512.jpeg",
"Ranking":3,
"IsNobility":0,
"NobilityType":0,
"NobilityLevel":0,
"UserShowStyle":{
"NameColor":0,
"BorderColor":0,
"LiangMedal":0,
"DztCountDown":0,
"Mounts":0,
"LiveLevelCode":0,
"LiveRights":null
},
"LiveLevelUrl":null,
"IsStealth":false}
],
"LiveCharmSwitch":1,
"IsSelf":false
}
}
I want to use c # extraction
"UserID": 3974854,
"UserCharm": 114858,
"UserName": "jack",
"UserID":6231512,
"UserCharm":22644,
"UserName":"red.girl",
That is to extract UserID, UserCharm, UserName,This json has many layers,
What I want after the extraction is,id is sorted in order
id = 1, UserID = 3974854, UserCharm = 114858, UserName = jack
id = 2, UserID = 6231512, UserCharm = 22644, UserName = red.girl
I use the following code, but only extract the first one
string json = #"{"Sucess":true,"Code":0,"Msg":"Sucess","Data":{"UserDayRanking":{"UserID":11452112,"UserCharm":0,"UserName":"gay","UserGender":1,"UserLevel":36,"UserPhoto":"http://res.xxx.com/2020/3/16/63719926625601201487545U11452112.jpeg","Ranking":0,"IsNobility":0,"NobilityType":0,"NobilityLevel":0,"UserShowStyle":null,"LiveLevelUrl":null,"IsStealth":false},"DayRankingList":[{"UserID":3974854,"UserCharm":114858,"UserName":"jack","UserGender":1,"UserLevel":91,"UserPhoto":"http://res.xxx.com/2020/2/15/63717400601924412312384U3974854.jpeg","Ranking":2,"IsNobility":1,"NobilityType":1,"NobilityLevel":3,"UserShowStyle":{"NameColor":100102,"BorderColor":100403,"LiangMedal":0,"DztCountDown":0,"Mounts":100204,"LiveLevelCode":0,"LiveRights":null},"LiveLevelUrl":null,"IsStealth":false},{"UserID":6231512,"UserCharm":22644,"UserName":"red.girl","UserGender":1,"UserLevel":57,"UserPhoto":"http://res.xxx.com/2019/11/20/63709843050801519858823U6231512.jpeg","Ranking":3,"IsNobility":0,"NobilityType":0,"NobilityLevel":0,"UserShowStyle":{"NameColor":0,"BorderColor":0,"LiangMedal":0,"DztCountDown":0,"Mounts":0,"LiveLevelCode":0,"LiveRights":null},"LiveLevelUrl":null,"IsStealth":false}],"LiveCharmSwitch":1,"IsSelf":false}}";
List<Info> jobInfoList = JsonConvert.DeserializeObject<List<Info>>(z);
foreach (Info jobInfo in jobInfoList)
{
//Console.WriteLine("UserName:" + jobInfo.UserName);
}
public class Info
{
public string UserCharm { get; set; }
public string UserName { get; set; }
public data DayRankingList { get; set; }
}
public class data
{
public int UserID { get; set; }
public string UserCharm { get; set; }
public string UserName { get; set; }
public string UserGender { get; set; }
public string UserLevel { get; set; }
}
The above code only shows username = jack,Never show username = red.girl
As it looks to me then you want some details from your JSON has the which is in DayRankingList. As you only want some data then we can use a tool like http://json2csharp.com/ to create our classes and then remove what we don't need. Then we end up with the following classes.
public class DayRankingList
{
public int UserID { get; set; }
public int UserCharm { get; set; }
public string UserName { get; set; }
}
public class Data
{
public List<DayRankingList> DayRankingList { get; set; }
}
public class RootObject
{
public Data Data { get; set; }
}
Which you can deserialise like this
string json = .....
var root = JsonConvert.DeserializeObject<RootObject>(json);
Then if you wish, you can extract the inner data into a new List<> and then just work on that.
List<DayRankingList> rankingLists = root.Data.DayRankingList;
//Do something with this, such as output it
foreach(DayRankingList drl in rankingLists)
{
Console.WriteLine(String.Format("UserId {0} UserCharm {1} UserName {2}",drl.UserId, drl.UserCharm, drl.UserName));
}
You can use Json.Linq to parse your JSON into JObject and enumerate DayRankingList items (since it's an array). Then convert every item into data class and order the result sequence by UserID
var jObject = JObject.Parse(json);
var rankingList = (jObject["Data"] as JObject)?.Property("DayRankingList");
var list = rankingList.Value
.Select(rank => rank.ToObject<data>())
.OrderBy(item => item?.UserID);
foreach (var user in list)
Console.WriteLine($"{user.UserID} {user.UserName}");
Another way is copy your JSON, go to Edit->Paste Special->Paste JSON as classes menu in Visual Studio and generate a proper class hierarchy (I've got 5 classes, they are quite long to post here), then use them during deserialization
The most type-safe way is to define the class structure that you want, like jason.kaisersmith suggested.
To have the final format you need, though, you might want to do an extra Linq Order and Select, to include the id:
var finalList = rankingLists.OrderBy(rl => rl.UserId).Select((value, index) => new
{
id = index,
value.UserId,
value.UserCharm,
value.UserName
});
foreach (var drl in finalList)
{
Console.WriteLine($"Id = {drl.id}, UserId = {drl.UserId}, UserCharm = {drl.UserCharm}, UserName = {drl.UserName}");
}
We are using elastic search just for document search in our application so we don't have any one expert in it. I was able to use TermQuery, SimpleQueryStringQuery and MatchPhraseQuery successfully. But I found out in documentation that using From & Size for pagination is not good for production and Search After is recommended.
But my implementation return null. It is confusing for me what should be in <Project> parameter as shown in Nest API Object Initializer Syntax in docs here.
My code looks like this:
var request = new SearchRequest<ElasticSearchJsonObject._Source>
{
//Sort = new List<ISort>
//{
// new SortField { Field = Field<ElasticSearchJsonObject>(p=>)}
//},
SearchAfter = new List<object> {
},
Size = 20,
Query = query
};
Reality is I don't understand this. Over here ElasticSearchJsonObject._Source is the class to map returned results.
My documents are simple text documents and I only want documents sorted according to score so document Id is not relevant.
There was already a question like this on SO but I can't find it somehow.
Update
After looking at answer I updated my code and though query obtained does work. It return result in kibana but not in NEST.
This is the new updated code:
var request = new SearchRequest<ElasticSearchJsonObject.Rootobject>
{
Sort = new List<ISort>
{
new SortField { Field = "_id", Order = SortOrder.Descending}
},
SearchAfter = new List<object> {
"0fc3ccb625f5d95b973ce1462b9f7"
},
Size = 1,
Query = query
};
Over here I am using size=1 just for test as well as hard code _id value in SearchAfter.
The query generated by NEST is:
{
"size": 1,
"sort": [
{
"_id": {
"order": "desc"
}
}
],
"search_after": [
"0fc3ccb625f5d95b973ce1462b9f7"
],
"query": {
"match": {
"content": {
"query": "lahore",
"fuzziness": "AUTO",
"prefix_length": 3,
"max_expansions": 10
}
}
}
}
The response from the ES does say successful but no results are returned.
Results do return in Kibana
Query status is successful
But...
Total returned is 0 in NEST
Sort value is null in kibana I used TrackScores = true to solve this issue
Here is the debug information:
Valid NEST response built from a successful low level call on POST: /extract/_source/_search?typed_keys=true
# Audit trail of this API call:
- [1] HealthyResponse: Node: http://localhost:9200/ Took: 00:00:00.1002662
# Request:
{"size":1,"sort":[{"_id":{"order":"desc"}}],"search_after":["0fc3ccb625f5d95b973ce1462b9f7"],"query":{"match":{"content":{"query":"lahore","fuzziness":"AUTO","prefix_length":3,"max_expansions":10}}}}
# Response:
{"took":3,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":0,"max_score":null,"hits":[]}}
So please tell me where I am wrong and what can be the problem and how to solve it.
Update 2:
Code in Controller:
Connection String:
var node = new Uri("http://localhost:9200");
var settings = new ConnectionSettings(node);
settings.DisableDirectStreaming();
settings.DefaultIndex("extract");
var client = new ElasticClient(settings);
Query:
var query = (dynamic)null;
query = new MatchQuery
{
Field = "content",
Query = content,
Fuzziness = Fuzziness.Auto,
PrefixLength = 3,
MaxExpansions = 10
};
Query Builder
var request = new SearchRequest<ElasticSearchJsonObject.Rootobject>
{
Sort = new List<ISort>
{
new SortField { Field = "_id", Order = SortOrder.Descending}
},
SearchAfter = new List<object> {
documentid //sent as parameter
},
Size = 1, //for testing 1 other wise 10
TrackScores = true,
Query = query
};
JSON Query
I use this code to get query I posted above. This query is then passed to kibana with GET <my index name>/_Search and there it works
var stream = new System.IO.MemoryStream();
client.SourceSerializer.Serialize(request, stream);
var jsonQuery = System.Text.Encoding.UTF8.GetString(stream.ToArray());
ES Response
string responseJson = "";
ElasticSearchJsonObject.Rootobject response = new ElasticSearchJsonObject.Rootobject();
var res = client.Search<object>(request);
if (res.ApiCall.ResponseBodyInBytes != null)
{
responseJson = System.Text.Encoding.UTF8.GetString(res.ApiCall.ResponseBodyInBytes);
try
{
response = JsonConvert.DeserializeObject<ElasticSearchJsonObject.Rootobject>(responseJson);
}
catch (Exception)
{
var model1 = new LoginSignUpViewModel();
return PartialView("_NoResultPage", model1);
}
}
This is where things go wrong. Above debug information was captured from response
ElasticSearchJsonObject
Some how I think problem might be here somewhere? The class is generated by taking response from NEST in Search request.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ESAPI
{
public class ElasticSearchJsonObject
{
public class Rootobject
{
public int took { get; set; }
public bool timed_out { get; set; }
public _Shards _shards { get; set; }
public Hits hits { get; set; }
}
public class _Shards
{
public int total { get; set; }
public int successful { get; set; }
public int skipped { get; set; }
public int failed { get; set; }
}
public class Hits
{
public int total { get; set; }
public float max_score { get; set; }
public Hit[] hits { get; set; }
}
public class Hit
{
public string _index { get; set; }
public string _type { get; set; }
public string _id { get; set; }
public float _score { get; set; }
public _Source _source { get; set; }
}
public class _Source
{
public string content { get; set; }
public Meta meta { get; set; }
public File file { get; set; }
public Path path { get; set; }
}
public class Meta
{
public string title { get; set; }
public Raw raw { get; set; }
}
public class Raw
{
public string XParsedBy { get; set; }
public string Originator { get; set; }
public string dctitle { get; set; }
public string ContentEncoding { get; set; }
public string ContentTypeHint { get; set; }
public string resourceName { get; set; }
public string ProgId { get; set; }
public string title { get; set; }
public string ContentType { get; set; }
public string Generator { get; set; }
}
public class File
{
public string extension { get; set; }
public string content_type { get; set; }
public DateTime last_modified { get; set; }
public DateTime indexing_date { get; set; }
public int filesize { get; set; }
public string filename { get; set; }
public string url { get; set; }
}
public class Path
{
public string root { get; set; }
public string _virtual { get; set; }
public string real { get; set; }
}
}
}
I am sure this can be used to get response.
Please note that in case of simple search this code works:
so for this query below my code is working:
var request = new SearchRequest
{
From = 0,
Size = 20,
Query = query
};
Using from/size is not recommended for deep pagination because of the amount of documents that need to be fetched from all shards for a deep page, only to be discarded when finally returning an overall ordered result set. This operation is inherent to the distributed nature of Elasticsearch, and is common to many distributed systems in relation to deep pagination.
With search_after, you can paginate forward through documents in a stateless fashion and it requires
the documents returned from the first search response are sorted (documents are sorted by _score by default)
passing the values for the sort fields of the last document in the hits from one search request as the values for "search_after": [] for the next request.
In the Search After Usage documentation, a search request is made with sort on NumberOfCommits descending, then by Name descending. The values to use for each of these sort fields are passed in SearchAfter(...) and are the values of Project.First.NumberOfCommits and Project.First.Name properties, respectively. This tells Elasticsearch to return documents that have values for the sort fields that correspond to the sort constraints for each field, and relate to the values supplied in the request. For example, sort descending on NumberOfCommits with a supplied value of 775 means that Elasticsearch should only consider documents with a value less than 775 (and to do this for all sort fields and supplied values).
If you ever need to dig further into any NEST documentation, click the "EDIT" link on the page:
which will take you to the github repository of the documentation, with the original asciidoc markdown for the page:
Within that page will be a link back to the original NEST source code from which the asciidoc was generated. In this case, the original file is SearchAfterUsageTests.cs in the 6.x branch
I have seen this done in code once or twice but can't find an example now. Until recently I was working in webforms and have switched to MVC. I have looked around and not found a whole lot on this. The code below is from my controller to pull in the values and display in my view model. I need to take the m.body.MembersId from MSMQ. I know what the problem is I just dont know how to use Linq like this.
The Situation , I need to do all this in one line. Cast the memberIds information that was originally a list named MembersId back to a list to display it but also do a string.join so that the entire list is displayed as one string. While I am aware of how to do both of those by themselves but to do in one line is proving beyond me. I will openly admit I am fairly new to linq and am learning as I go.
This is the class
public class MsgChildClass{
public string SourceSystem { get; set; }
public List<string> MemberIds { get; set; }
public string ParentId { get; set; }
public string Error { get; set; }
}
this is the function
public ActionResult GetAllMessages() {
string queueName = (ViewBag.QueueName != null) ? ViewBag.QueueName : Request.QueryString["queueName"];
Session["CurrentQueueName"] = queueName;
TempData["queueName"] = queueName;
ViewBag.QueueName = queueName;
var queue = _Queues[queueName];
queue.MessageReadPropertyFilter.ArrivedTime = true;
queue.MessageReadPropertyFilter.Body = true;
queue.Formatter = new JsonMessageFormatter();
var messages = queue.GetMessages();
var model = messages.Select(m =>
new ViewModel() {
Id = m.Id,
Date = m.ArrivedTime,
SourceSystem = ((MsgChildClass)m.Body).SourceSystem,
DeletedMemberIds = ((MsgChildClass)m.Body).DeletedMemberIds,//OrderByDescend(x => x); string.Join(",",((MsgChildClass)m.Body).DeletedMemberIds),
ParentMemberId = ((MsgChildClass)m.Body).ParentId,
Error = ((MsgChildClass)m.Body).Error,
QueName = queueName
}).ToList();
return Json(model.ToList(), JsonRequestBehavior.AllowGet);
}
View Model
public class ViewModel
{
[Required]
public string Id { get; set; }
//[Required]
[Display(Name = "Arrival Time")]
public DateTime Date { get; set; }
[Required]
[Display(Name = "Source System")]
public string SourceSystem { get; set; }
[Required]
[Display(Name = "Member Ids")]
public List <string> MemberIds { get; set; }
[Required]
[Display(Name = "Parent Member Id")]
public string ParentMemberId { get; set; }
[Display(Name = "Error")]
public string Error { get; set; }
[Display(Name = "QueName")]
public string QueName { get; set; }
}
This is what I have. All of it works correctly except the memberids. Debugging shows me that the memberids have the value but I am not drilling down far enough. So hopefully some one can help me out quite a bit as been quite few hours at this point. Google is great but he didnt help me out with this one.
It's cleaner and more efficient if you only cast once into a variable. And another advantage is that you can add a break point and look at msgChild.
var model = messages.Select(m =>
{
var msgChild = (MsgChildClass)m.Body;
return new ViewModel
{
Id = m.Id,
Date = m.ArrivedTime,
SourceSystem = msgChild.SourceSystem,
MemberIds = msgChild.MemberIds,
ParentMemberId = msgChild.ParentId,
Error = msgChild.Error,
QueName = queueName
};
}).ToList();
The code was correct which was the maddening part. debugger was telling me the values were there. But the part I didnt look at was how the datatable.js was loading the data for display. After seeing that was done incorrect, I corrected it and now the list is now displayed as string , string, string which is what I was needing so thanks every one
My Code goes like this:
using (StreamReader streamReader1 = new StreamReader(response.GetResponseStream()))
{
string resultString = streamReader1.ReadToEnd();
var ser = new DataContractJsonSerializer(typeof(RootObject));
var stream = new MemoryStream(Encoding.Unicode.GetBytes(resultString));
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(RootObject));
RootObject myBook = (RootObject)jsonSerializer.ReadObject(stream);
Deployment.Current.Dispatcher.BeginInvoke(() => Shops.ItemsSource = myBook.SearchResponse.Spell.Results); }
public class Query
{
public string SearchTerms { get; set; }
}
public class Result
{ [DataMember(IsRequired=false)]
public string Value { get; set; }
}
public class Spell
{
[DataMember(IsRequired = false)]
public int Total { get; set; }
[DataMember(IsRequired = false)]
public List<Result> Results { get; set; }
}
public class SearchResponse
{
public bool IsRequired { get; set; }
public string Version { get; set; }
public Query Query { get; set; }
public Spell Spell { get; set; }
}
public class RootObject
{
public SearchResponse SearchResponse { get; set; }
}
IF JSON DATA EXISTS
{"SearchResponse":{"Version":"2.0","Query":{"SearchTerms":"mispell"},"Spell":{"Total":1,"Results":[{"Value":"misspell"}]}}}
IF JSON DATA DOES NOT EXIST
{"SearchResponse":{"Version":"2.0","Query":{"SearchTerms":"mispel"}}}
The thing is, if Bing doesn't detect a wrong word, it crashes and gives me an error like NullReferenceException. I have tried to do an IF statement looking at the stream for if it's value is blank but doesn't seem to work.
Any ideas?
If you receive a JSON answer without the Spell part, the Spell property in SearchResponse will be null. If it's null, you may not dereference it like this:
myBook.SearchResponse.Spell.Results
(This hasn't anything to do with JSON. It's how C# works.)
So instead of:
Shops.ItemsSource = myBook.SearchResponse.Spell.Results
you probably want to write:
if (myBook.SearchResponse.Spell = null)
Shops.ItemsSource = myBook.SearchResponse.Spell.Results;
else
Shops.ItemsSource = new List<Result>();
For your next question: It would be very helpful if your questions would show the exact error message including the stack trace (or at least the exact line where it occurred).
Use [DataMember(IsRequired=false)], MSDN: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.isrequired.aspx