RestSharp (C#) - Deserialize JSON Objects to NULL - c#

I'm trying to understand REST by utilizing RestSharp in my application.
Here is a bit of JSON that my client is returning:
{
"result" : {
"object_type" : "session",
"user_id" : "FEE3CBD4-5D35-11E3-A42A-606A40E381E5",
"object_name" : "Session",
"id" : "2F2968B6-5D37-11E3-89F4-5D6A40E381E5"
}
}
Here is my class object:
public class TGCResult : IDeserializer
{
public string object_type {get; set;}
public string user_id { get; set; }
public string object_name { get; set; }
public string id { get; set; }
public TGCResult()
{
}
public override string ToString()
{
return "object_type = " + object_type + "\nuser_id = " + user_id + "\nobject_name = " + object_name + "\nid = " + id;
}
}
And here is the code in which I am retrieving the JSON and attempting to deserialize:
var client = new RestClient("https://www.xxxxxxxxx.com");
var request = new RestRequest("/api/session", Method.POST);
request.AddParameter("username", "JSventoraGD");
request.AddParameter("password", "xxxxxxxxxxxxxxxx");
request.AddParameter("api_key_id", "xxxxxxxxxxxxxxxxxxx");
request.RequestFormat = DataFormat.Json;
var asyncHandle = client.ExecuteAsync<TGCResult>(request, response =>
{
TxtTest.Text = response.Data.ToString();
});
asyncHandle.Abort();
When doing this, I can see the data is returned to my application correctly, but the Data in my response always has NULL values. Any ideas on why this might be happening? Am I supposed to manually deserialize the JSON given the content? The samples I've seen online have a very similar setup to mine, I'm lost... any help is greatly appreciated!

var asyncHandle=client.ExecuteAsync(request,response=>{
String res=response.Content;
T obj = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(res);
});

Try adding
request.RootElement = "result";
I have just spent a couple of hours trying to get a simple GET request to parse anything but null, setting RootElement helped me. Bit surprised i needed it since you set your type class several other places in the code.

Try using it like this
var asyncHandle = client.ExecuteAsync(request, response =>
{
var json = response.Content;
// deserialize to TGCResult
});
This works fine for me

It seems you need to have another class as your Data type.
public class TGCResultContainer
{
public TGCResult result { get; set; }
}
Also, your TGCResult class does not need to implement IDeserializer.

Related

ElasticSearch NEST searchresponse.hits data not populated

I have an index in ElasticSearch. I have setup an ASP.NET core lambda serverless app. I inject IElasticClient into my controller.
I want my controller to be signed as public IEnumerable<StreamSummary> Get() and the ElasticSearch query I would have thought to be as as simple as return searchResponse.Hits.Select(h => h.Source).ToList(); but this is not the case as can be seen below.
I query my Index with something basic like this
var searchResponse = elasticClient.Search<StreamSummary>(s => s
.Index("myindex")
.Query(q => q.MatchAll()
)
);
When I log how many "hits" I get, it is the correct amount (searchResponse.Hits.Count).
When I set my controller return IEnumerable<StreamSummary> and use searchResponse.Hits.Select(h => h.Source).ToList() the list is the correct number but every entry has no values. DateTime fields are all Datetime.Min strings are empty, nullables are null. It's basically an empty/freshly instantiated class and not populated/serialised as I would have expected it to be.
When I iterate the hits and display/log Index,Type and Id, this all works and displays exactly as I expect. The Issue I am having is with _source (Source Property NEST).
foreach (var searchResponseHit in searchResponse.Hits)
{
hits.Add(searchResponseHit.Index);
hits.Add(searchResponseHit.Type);
hits.Add(searchResponseHit.Id); searchResponseHit.Source
searchResponseHit.Source // here is the problem, no populated StreamSummary data}
Where hits is List<string> hits = new List<string>();
So I dig a bit further and in my Startup.cs I DisableDirectStreaming() on ConnectionSettings() so I can get at the request/response buffered byte streams.
I then do the following:
var requestJson = System.Text.Encoding.UTF8.GetString(searchResponse.ApiCall.RequestBodyInBytes);
var responseJson = System.Text.Encoding.UTF8.GetString(searchResponse.ApiCall.ResponseBodyInBytes);
return searchResponse.ApiCall.HttpMethod.ToString() + searchResponse.ApiCall.Uri + "\n" + requestJson + "\r\n" + responseJson;
This is an inccomplete/part response but as you can see it contains a lot of escape characters etc. (Could this be part of the problem, a serialisation issue??)
\"hits\" : {\n \"total\" : {\n \"value\" : 9,\n \"relation\" : \"eq\"\n },\n \"max_score\" : 1.0,\n \"hits\" : [\n {\n \"_index\" : \"accounts\",\n \"_type\" : \"_doc\",\n \"_id\" : \"U3P 1 8fb4b770-4e29-4f0d-aec8-1bcd4199005f\",\n \"_score\" : 1.0,\n \"_source\" : {\n \"ProcessingResponse\" : \"Success\",\n \"ProviderId\" : 6,\n
Connection/Client:
var uri = new Uri(Configuration["ElasticSearch:Url"]);
var httpConnection = new AwsHttpConnection(new BasicAWSCredentials(Configuration["AWS:AwsAccessKeyId"], Configuration["AWS:AwsSecretAccessKey"]),
RegionEndpoint.GetBySystemName(Configuration["ElasticSearch:Region"]));
var pool = new SingleNodeConnectionPool(uri);
var config = new ConnectionSettings(pool, httpConnection).DefaultIndex(Startup.ElasticSearchIndex)
.DisableDirectStreaming().PrettyJson();
var elasticClient = new ElasticClient(config);
services.AddSingleton<IElasticClient>(elasticClient);
POCO is:
public class StreamSummary : ResponseSummary
{
public string Type { get; set; }
public int? ProviderId { get; set; }
public string ProviderAccount { get; set; }
public int? ProcessingTime { get; set; }
public DateTime ProcessedTimeUtc { get; set; }
}
where Response Summary Contains a couple of nullable decimals(but also has an IList<AnotherClass>)
Help Appreciated.
If I'm not mistaken, this is what you're after:
searchResponse.Documents

Deserialize JSON to list with unknown object name in C#

I want to deserialize following JSON.
The problem is that the objects "ANDE" & "DAR" can change.
Means the objects are unknown and change depending on the JSON i wanna deserialize.
About 8000 different objects (ANDE, DAR, ...) need to be deserialized.
{"ANDE":
{"chart":[
{"date":"20180914","minute":"09:30"},{"date":"20180914","minute":"13:30"}]},
"DAR":
{"chart":[
{"date":"20180914","minute":"09:30"},{"date":"20180914","minute":"13:30"}]}}
I get the data by HTTP response and want to put into a List:
HttpResponseMessage response = client.GetAsync(API_PATH).GetAwaiter().GetResult();
List historicalDataList = response.Content.ReadAsAsync<List<HistoricalDataResponse>>().GetAwaiter().GetResult();
The HistoricalDataResponse class looks like:
public class HistoricalDataResponse
{
public string date { get; set; }
public string minute { get; set; }
}
How can i deserialize this kind of JSON with unknown objects in C#?
Any help is highly appreciated.
Then you should use a dynamic variable:
dynamic ReturnValue = JsonConvert.DeserializeObject(jsonstring);
note that as in dynamic objects, properties are determined after being assigned in runtime, so you will not get a drop down menu in design time, and also as its properties are unknown in design time, and property you test in design time even if its not correct, you wont get an error, and you will get the error in runtime when it is assigned.
dynamic ReturnValue = JsonConvert.DeserializeObject(jsonstring);
try
{
var a = ReturnValue.ANDE; // will work if it has ANDE property.
// do what you would do with ANDE
}
catch{}
try
{
var a = ReturnValue.DAR; // will work if it has DAR property.
// do what you would do with DAR
}
catch{}
Use a dictionary with string as key type :
void Main()
{
var client = new HttpClient();
HttpResponseMessage response = client.GetAsync("url").GetAwaiter().GetResult();
var json = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var result = JsonConvert.DeserializeObject<Dictionary<string, DateResponse>>(json);
foreach (var element in result)
{
var key = element.Key; // ANDE
foreach (var item in element.Value.Chart)
{
var date = item.date;
var minute = item.minute;
}
}
}
public class DateResponse{
public List<HistoricalDataResponse> Chart { get; set; }
}
public class HistoricalDataResponse
{
public string date { get; set; }
public string minute { get; set; }
}

JsonConvert.SerializeObject failes when having a single quote

I have an object say:
public class Comment {
public string Id { get; set; }
public string Author { get; set; }
public string Body { get; set; }
}
And whenever I have a single quote in the body (the others vars will never have them)
the following line crashes:
return JObject.Parse("{ 'Result' : 'Sucessfull!', 'Comment' : '" + JsonConvert.SerializeObject(comment) + "' }");
And I'm sure it's on the body, because this only happens when I do something like this:
comment.Body = "testing th's ";
and the other values, are dynamicly set, and work for bodies without the single quotes.
any clue why this is happening?
Note: I need to upgrade the comment.Body to support new lines later on if that is relevant
Why do you add the comment object to your JSON as plain text? What you try to parse is this string:
{ 'Result' : 'Sucessfull!', 'Comment' : '{"Id":null,"Author":null,"Body":"testin
g th's"}' }
Obviously, it is not a valid JSON string. All you have to do is to rewrite your code a little bit:
return JObject.Parse("{ 'Result' : 'Sucessfull!', 'Comment' : " + JsonConvert.SerializeObject(comment) + " }");
Try this
Comment comment = new Comment()
{
Body = "testing th's ",
Author = "Author",
Id = "007"
};
var result = new
{
Result = "Sucessfull!",
Comment = comment
};
return JsonConvert.SerializeObject(result);

Internal error 500 on POST web api

I have a problem with my web api application. I get an internal error 500 when i try to post(save) a new user in my db.
The function bellow is the one that i use to make the client call.
public void InsertNewUser(RegisterModel pNewUser, string pEmail)
{
// Build rest uri
string lREST_Uri_Browse = string.Format(#"api/accountapi/saveuserdata"
// User data
/*pModelSerialized*/);
// Complete URI
string lREST_Uri = Helpers_API.endPoint + lREST_Uri_Browse;
var client = new HttpClient();
client.BaseAddress = new Uri(Helpers_API.endPoint);
var newUser = new Models.Models_API.Users
{
Email = pNewUser.Email,
FName = pNewUser.FName,
LName = pNewUser.LName,
Inserted = DateTime.Now,
ActiveAcc = true,
AccType = pNewUser.AccType,
BCompanyID = pNewUser.CompanyID,
PID = pNewUser.PID,
Password = pNewUser.Password,
Token = GetToken(pEmail),
ThirdParty = 0,
Gender = pNewUser.Gender,
BirthDate = pNewUser.BirthDate
};
// Add an Accept header for JSON format.
//client.DefaultRequestHeaders.Accept.Add(
// new MediaTypeWithQualityHeaderValue("application/json"));
// Create the JSON formatter.
MediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
// Use the JSON formatter to create the content of the request body.
HttpContent content = new ObjectContent<Models.Models_API.Users>(newUser, jsonFormatter);
var result = client.PostAsync(lREST_Uri_Browse, content).Result;
}
This is the model
public class Users
{
public int BrokerID { get; set; }
public DateTime Inserted { get; set; }
public string Email { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public bool ActiveAcc { get; set; }
public int BCompanyID { get; set; }
public int PID { get; set; }
public int AccType { get; set; }
public string Password { get; set; }
public string Token { get; set; }
public int Gender { get; set; }
public DateTime BirthDate { get; set; }
public int ThirdParty { get; set; }
}
And bellow is the POST in APIController:
public HttpResponseMessage SaveUserData(Users pNewUser)
{
bool createUser = false;
// First check for provided email in DB
Users existingUser = asigCtx.Users.Where(u => u.Email == pNewUser.Email).SingleOrDefault();
if (existingUser == null)
createUser = true;
else if (existingUser.ActiveAcc)
createUser = true;
if (createUser)
{
using (asigCtx = new AsigPrimeContext())
{
Users user = new Users()
{
Email = pNewUser.Email,
FName = pNewUser.FName,
LName = pNewUser.LName,
Inserted = DateTime.Now,
ActiveAcc = true,
AccType = pNewUser.AccType,
BCompanyID = pNewUser.BCompanyID,
PID = pNewUser.PID,
Password = pNewUser.Password,
Token = pNewUser.Token,
ThirdParty = 0,
Gender = pNewUser.Gender,
BirthDate = pNewUser.BirthDate,
};
asigCtx.Users.Add(user);
asigCtx.SaveChanges();
}
}
var response = Request.CreateResponse<Users>(HttpStatusCode.Created, pNewUser);
return response;
}
Can anyone give me piece of advice with this code because i'm new in this and i just want to do it wright. TNX
You have an error in your code. A 500 error indicates that your code contains an unhandled exception that killed its worker process.
Change your web.config file so that your application outputs the full error message.
A few things I would check/try to get to the bottom of the issue:
Is the code above exactly the same as in your application or have you changed anything (even if only to make it simpler)?
Is the Users object used in SaveUserData controller method definitely from the same assembly as the one that you are posting from the InsertNewUser method?
Is the Users object complete on the listing (e.g. does it have any constructors)?
Have you tried executing the request to the endpoint through fiddler? This way you take any potential bugs in the client call out of the equation to see if the controller method on its own works.
I've noticed this line:
string lREST_Uri_Browse = string.Format(#"api/accountapi/saveuserdata"
// User data
/*pModelSerialized*/);
Are you formatting the url and passing any params to it? If so, what are the params and what does your WebApi route look like?
That should be enough for a start - let me know how you get on.
BTW: Two things that strike me in your code (unrelated to the question):
It's very confusing to have a class called 'Users' representing a single user. If it's you're code I'd advise to change that to singular.
the properties on the Users object are using abbreviations - I don't think it's that expensive to spell them out and I can guarantee you that anyone new to this code will be grateful if you put a full name rather than a mysterious BCompanyID, or less mysterious but still hard to read (and write for that matter) FName
I had the same problem a few weeks ago. After doing a few tests, I've realized that my WebApi application was using DataContractJsonSerializer by default, instead of Newtonsoft. To fix it, you can change the default serializer on your server to NewtonSoft or to use DatacontractJsonSerializer to serialize your object and pass it to HttpWebRequest.
I would use jQuery to post some Json to the same URL ($.post(#"api/accountapi/saveuserdata", { Email: "e#example.com", FName = "Vlad" ... })), thus eliminating InsertNewUser from the equation. If you still get a null pNewUser parameter in SaveNewuser, then I would look at your API's route configuration to make sure the server expects SaveUserData(Users). If you get a non-null pNewUser from jQuery, then I would look closer at the output from InsertNewUser. If I had to bet, I would put my money on the routing configuration.
it seemed that i had an error with the LINQ code
Users existingUser = asigCtx.Users.Where(u => u.Email == pNewUser.Email).SingleOrDefault();
After i solved this the request was ok.
Tnx for the help :) Appreciate.

Json C# : deserializing a changing content or a piece of json response

I use an Api that is returning not everytime the same response based in the place demanded. Some places have more details, some contents have more attributes that others. The resulting serialized object is not the same everytime resulting in deserializing error when not match. The object of this project is not match the entire content response, but only one piece of this content : the Centroid.
{
"place":{
"woeid":12345,
"placeTypeName":"State",
"placeTypeName attrs":{
"code":8
},
"name":"My Region",
"country":"",
"country attrs":{
"type":"Country",
"code":"XX"
},
"admin1":"My Region",
"admin1 attrs":{
"type":"Region",
"code":""
},
"admin2":"",
"admin3":"",
"locality1":"",
"locality2":"",
"postal":"",
"centroid":{
"latitude":30.12345,
"longitude":40.761292
},
"boundingBox":{
"southWest":{
"latitude":32.2799,
"longitude":50.715958
},
"northEast":{
"latitude":29.024891,
"longitude":12.1234
}
},
"areaRank":10,
"popRank":0,
"uri":"http:\/\/where.yahooapis.com",
"lang":"en-US"
}
}
Can someone point the best method to deserialize a piece of content instead the complete response (centroid not at same place), or to deserialize a changing response schema.
I use ServiceStack C# serializer but all propositions are welcome. Thanks.
There's actually a few ways you can parse this using ServiceStack's JsonSerializer as can be seen in this example of parsing one of GitHub's JSON API.
I would take the JsonObject approach as you get to end up with the C# class of your choice, although it does require more than the 1-liner that you're used to with ServiceStack's JsonSerializer. Anyway here's the resulting code:
Func<JsonObject, Centroid> toCentroid = map =>
new Centroid(map.Get<decimal>("latitude"), map.Get<decimal>("longitude"));
var place = JsonObject.Parse(JsonCentroid)
.Object("place")
.ConvertTo(x => new Place
{
WoeId = x.Get<int>("woeid"),
PlaceTypeName = x.Get(""),
PlaceTypeNameAttrs = x.Object("placeTypeName attrs"),
Name = x.Get("Name"),
Country = x.Get("Country"),
CountryAttrs = x.Object("country attrs"),
Admin1 = x.Get("admin1"),
Admin1Attrs = x.Object("admin1 attrs"),
Admin2 = x.Get("admin2"),
Admin3 = x.Get("admin3"),
Locality1 = x.Get("locality1"),
Locality2 = x.Get("locality2"),
Postal = x.Get("postal"),
Centroid = x.Object("centroid")
.ConvertTo(toCentroid),
BoundingBox = x.Object("boundingBox")
.ConvertTo(y => new BoundingBox
{
SouthWest = y.Object("southWest").ConvertTo(toCentroid),
NorthEast = y.Object("northEast").ConvertTo(toCentroid)
}),
AreaRank = x.Get<int>("areaRank"),
PopRank = x.Get<int>("popRank"),
Uri = x.Get("uri"),
Lang = x.Get("lang"),
});
Here is the full source code of this example.
You could use the DataContractJsonSerializer that's part of the standard .NET framework. You define just those attributes you're interested in. The other ones will be ignored.
class CentroidReader
{
public static Centroid ReadControid(Stream stream)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Response));
Response response = serializer.ReadObject(stream) as Response;
return response.Place.Centroid;
}
}
[DataContract]
class Response
{
[DataMember(Name = "place")]
public Place Place { get; set; }
}
[DataContract]
class Place
{
[DataMember(Name = "centroid")]
public Centroid Centroid { get; set; }
}
[DataContract]
class Centroid
{
[DataMember(Name = "latitude")]
public double? Latitude { get; set; }
[DataMember(Name = "longitude")]
public double? Longitude { get; set; }
}

Categories