JsonConvert not working on list of structures inside class - json

Hello i want to deserialize a class which contains a string, a bool and a List<[mystructtype>;When using JsonConvert.Deserialize<[myclass]> it deserializes the string and the bool correctly but not the List<[Struct]>.I have also changed the List<struct> with an array of structs.Both the class container and the struct are marked with Serializeable and i do not understand where the problem is.
Can anyone help me?
Struct
[Serializable]
public struct Status
{
//identifiers
public long playerId { get; set; }
public long groupId { get; set; }
public int type { get; set; }
}
Class Container
[Serializable]
class GatewayDeviceResponse
{
public bool status { get; set; } //gets deserialized good
public string message { get; set; } //gets deserialized good
public Status[] data { get; set; } // all members are defaults
}
Deserialization
IRestResponse response = client.Execute(request);
string result = Encoding.UTF8.GetString(response.RawBytes);
GatewayDeviceResponse resp = JsonConvert.DeserializeObject<GatewayDeviceResponse>(result);
return resp.data.ToList();
P.S The string is a response from a webserver,and i am using RestSharp for creating the server request and getting the response.The thing is the response string is good.The class is deserialized good excluding the collection.
What could the problem be?
P.S
The string response from the server i get is :
"{
\"status\":true,
\"message\":\"ok\",
\"data\":[
{
\"status\":{
\"playerId\":59,
\"groupId\":26,
\"type\":2,
\"deviceId\":\"abababa",
\"groupName\":\"srl\",
\"playerName\":\"Adrian\"
}
},
{
\"status\":{
\"playerId\":25,
\"groupId\":26,
\"type\":1,
\"deviceId\":\"lalal\",
\"groupName\":\"srl\",
\"playerName\":\"Alex\"
}
}
]
}"
The Status[] array elements are not supposed to be fully filled by the server response , just the 3 fields i have posted in the POCO/

I wrote a unit test as below and it passes and correctly deserialized with restsharp. Can you replace your response string and classes to check unit test still pass?
May be your class representation is not fit for your response. Take a little help from http://json2csharp.com/ and check your classes represents your json correctly.
[Test]
public void Can_Deserialize_Struct()
{
var data = "{ \"myList\":[{\"name\": \"test1234\"}] }";
JsonDeserializer json = new JsonDeserializer();
var output = json.Deserialize<MyTest>(new RestResponse { Content = data });
Assert.NotNull(output);
}
class MyTest
{
public List<MyStruct> MyList { get; set; }
}
struct MyStruct
{
public String name { get; set; }
}
According to your response string, your c# classes should represent your json as below :
public class Status
{
public int playerId { get; set; }
public int groupId { get; set; }
public int type { get; set; }
public string deviceId { get; set; }
public string groupName { get; set; }
public string playerName { get; set; }
}
public class StatusData
{
public Status status { get; set; }
}
public class GatewayDeviceResponse
{
public bool status { get; set; }
public string message { get; set; }
public List<StatusData> data { get; set; }
}
It does not related with type struct or class. You need to add another class in front of your status representation class. Because it starts as a json object in your response string.

Related

How to read json request body array object?

I am sending data in a post request as follow:
{
"HospitalId": "Hospital-0232",
"DataSliceTimestamp": "2020.08.10",
"HourQuarter": "00:01",
"Data": [
{"country":"US","state":"MS","county":"bolivar","lat":32.354668,"lng":-89.398528,"type":"ICU","measure":"1000HAB","beds":0.241539,"population":33121,"year":2014,"source":"khn","source_url":"https://khn.org/news/as-coronavirus-spreads-widely-millions-of-older-americans-live-in-counties-with-no-icu-beds/"},
{"country":"US","state":"MS","county":"bolivar","lat":32.354668,"lng":-89.398528,"type":"ICU","measure":"1000HAB","beds":0.241539,"population":33121,"year":2015,"source":"khn","source_url":"https://khn.org/news/as-coronavirus-spreads-widely-millions-of-older-americans-live-in-counties-with-no-icu-beds/"},
{"country":"US","state":"MS","county":"bolivar","lat":32.354668,"lng":-89.398528,"type":"ICU","measure":"1000HAB","beds":0.241539,"population":33121,"year":2016,"source":"khn","source_url":"https://khn.org/news/as-coronavirus-spreads-widely-millions-of-older-americans-live-in-counties-with-no-icu-beds/"},
{"country":"US","state":"MS","county":"bolivar","lat":32.354668,"lng":-89.398528,"type":"ICU","measure":"1000HAB","beds":0.241539,"population":33121,"year":2017,"source":"khn","source_url":"https://khn.org/news/as-coronavirus-spreads-widely-millions-of-older-americans-live-in-counties-with-no-icu-beds/"},
{"country":"US","state":"MS","county":"bolivar","lat":32.354668,"lng":-89.398528,"type":"ICU","measure":"1000HAB","beds":0.241539,"population":33121,"year":2018,"source":"khn","source_url":"https://khn.org/news/as-coronavirus-spreads-widely-millions-of-older-americans-live-in-counties-with-no-icu-beds/"}
]
}
And for reading the body I am doing it like this:
public class RequestBody
{
public string HospitalId { get; set; }
public string DataSliceTimestamp { get; set; }
public string HourQuarter { get; set; }
public string[] Data { get; set; }
}
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
RequestBody data = JsonConvert.DeserializeObject<RequestBody>(requestBody);
But I get error:
Newtonsoft.Json: Unexpected character encountered while parsing value: [. Path 'Data', line 5, position 13.
Something is wrong while reading array data, please guide.
You need to strongly type your JSON input to an object array not a string.
Here's an example of what the object could look like:
public class Datum
{
[JsonProperty("country")]
public string country { get; set; }
[JsonProperty("state")]
public string state { get; set; }
[JsonProperty("county")]
public string county { get; set; }
[JsonProperty("lat")]
public double lat { get; set; }
[JsonProperty("lng")]
public double lng { get; set; }
[JsonProperty("type")]
public string type { get; set; }
[JsonProperty("measure")]
public string measure { get; set; }
[JsonProperty("beds")]
public double beds { get; set; }
[JsonProperty("population")]
public int population { get; set; }
[JsonProperty("year")]
public int year { get; set; }
[JsonProperty("source")]
public string source { get; set; }
[JsonProperty("source_url")]
public string source_url { get; set; }
}
public class RequestBody
{
[JsonProperty("HospitalId")]
public string HospitalId { get; set; }
[JsonProperty("DataSliceTimestamp")]
public string DataSliceTimestamp { get; set; }
[JsonProperty("HourQuarter")]
public string HourQuarter { get; set; }
[JsonProperty("Data")]
public IList<Datum> Data { get; set; }
}
You can then deserialize it like you're already doing:
RequestBody data = JsonConvert.DeserializeObject<RequestBody>(requestBody);
I solved this by using dynamic type and by pulling out data field from the request body.
// Reading body
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
// Parse through the request body string and make it in appropriate format.
dynamic RequestBody_data = JsonConvert.DeserializeObject(requestBody);
var Data = RequestBody_data["Data"].ToString();
Through this I was able to get the data field string and then I can split it with "}," to get all the rows. Thanks

C# JSON deserialization returns null

I'm trying to deserialize some statistics in JSON format from valve's API. The code below doesn't throw any exceptions when deserializing, only when trying to use the statistics afterwards. None of the statistics have a value after deserialization. Valve's response looks like this:
"playerstats":{
"steamID":"",
"gameName":"",
"stats":[
{
"name":"deaths",
"value":5062
}, etc etc..
This is my Rust class (Rust being the game I'm getting statistics from.):
public class Rust
{
public int steamID { get; set; }
public string gameName { get; set; }
public Array stats { get; set; }
}
And this is the deserialization code:
Rust getStats = JsonConvert.DeserializeObject<Rust>(str);
foreach (var stat in getStats.stats) //< ----- Exception: Object reference not set to an instance of an object.
{
parsed += stat.ToString();
}
'parsed' is then returned and used to print out all statistics and 'str' is the json response from Valve. I pasted the entire JSON response on pastebin in-case the above data isn't enough: https://pastebin.com/uJZSTF3G
I've tried naming some of the statistics individually in the Rust class instead of using an Array.
I expect the output to show all of the deserialized statistics for example in a console.
As #Bagus Tesa suggested, try something like...
public class Rust
{
public int steamID { get; set; }
public string gameName { get; set; }
public List<RustStat> stats { get; set; }
}
public class RustStat
{
public string name { get; set; }
public string value { get; set; }
}
Edit
I changed the steamID property to string and added the full code below. This compiled for me successfully. Hope this helps!
public class Valve
{
public Rust playerstats { get; set; }
}
public class Rust
{
public string steamID { get; set; }
public string gameName { get; set; }
public List<RustStat> stats { get; set; }
}
public class RustStat
{
public string name { get; set; }
public string value { get; set; }
}
Valve valve = JsonConvert.DeserializeObject<Valve>(str);
foreach (RustStat stat in valve.playerstats.stats)
{
}

JSON.NET Error reading string. Unexpected token: StartObject. Path 'responseData',

I am trying to deserialize this link , but I keep getting this error.
Error reading string. Unexpected token: StartObject. Path 'responseData'.
From what i have googled, the problem seems to be the setup of my object I'm trying to deserialize into. Below is my class:
public class FeedSearchResult
{
[JsonProperty("responseData")]
public String ResponseData { get; set; }
[JsonProperty("query")]
public String Query { get; set; }
[JsonProperty("entries")]
public string[] Entries { get; set; }
[JsonProperty("responseDetails")]
public object ResponseDetails { get; set; }
[JsonProperty("responseStatus")]
public String ResponseStatsu { get; set; }
}
public class ResultItem
{
[JsonProperty("title")]
public String Title { get; set; }
[JsonProperty("url")]
public String Url { get; set; }
[JsonProperty("link")]
public String Link { get; set; }
}
What am I doing wrong in my class? Any help would be greatly appreciated.
Your data model only has two levels of nesting, but the JSON returned has three. If you look at the formatted JSON using https://jsonformatter.curiousconcept.com/ you will see:
{
"responseData":{
"query":"Official Google Blogs",
"entries":[
{
"url":"https://googleblog.blogspot.com/feeds/posts/default",
"title":"\u003cb\u003eOfficial Google Blog\u003c/b\u003e",
"contentSnippet":"\u003cb\u003eOfficial\u003c/b\u003e weblog, with news of new products, events and glimpses of life inside \u003cbr\u003e\n\u003cb\u003eGoogle\u003c/b\u003e.",
"link":"https://googleblog.blogspot.com/"
},
In particular your data model has responseData as a String when it needs to be a contained object. This is the specific cause of the exception.
If you upload the JSON to http://json2csharp.com/ you will get the following data model, which can be used to deserialize this JSON:
public class ResultItem
{
public string url { get; set; }
public string title { get; set; }
public string contentSnippet { get; set; }
public string link { get; set; }
}
public class ResponseData
{
public string query { get; set; }
public List<ResultItem> entries { get; set; }
}
public class RootObject
{
public ResponseData responseData { get; set; }
//Omitted since type is unclear.
//public object responseDetails { get; set; }
public int responseStatus { get; set; }
}

ServiceStack: Deserializing a Collection of JSON objects

I have a simple json string which contains a collection of objects
http://sandapps.com/InAppAds/ads.json.txt
When I call GetAsync to get the objects, the collection returns 1 element instead of 4 and it's empty:
new JsonServiceClient ().GetAsync<List<CrossSell>> (url, Success, Failure);
My class is simple:
class CrossSell
{
public string ID { get; set; }
public string AppCategory { get; set; }
public string AppID { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
public string Copy { get; set; }
public string Device { get; set; }
public string Link { get; set; }
}
The JSON assumes a response DTO like:
class CrossSellResponse {
List<CrossSell> CrossSells { get; set; }
}
new JsonServiceClient().GetAsync<CrossSellResponse> (url, Success, Failure);
and not a bare array as your C# example suggests:
new JsonServiceClient ().GetAsync<List<CrossSell>> (url, Success, Failure);
I found the answer. You need to create an overall wrapper class that holds the JSON response. I call mine CrossSellResponse
public class CrossSellResponse
{
public List< CrossSell> CrossSells {get; set;}
}
The class CrossSell defines the data in the collection and matches the field names in a case sensitive way. The name of the response payload property CrossSells matches the name of the collection in the json stream.

JavaScriptSerializer Question

I am having some issues DeSerializing the following Json, it runs, throws no errors however the props in the class are all null so it is obviously not working.
{ "realms":[ { "type":"pve", "queue":false, "status":true, "population":"medium", "name":"Malfurion", "slug":"malfurion" } ] }
The above JSON is the jsonResult string so string jsonResult = the above JSON
My code:
public class Realm
{
public string type { get; set; }
public bool queue { get; set; }
public bool status { get; set; }
public string population { get; set; }
public string name { get; set; }
public string slug { get; set; }
}
var realm = javaScriptSerializer.Deserialize<Realm>(jsonResult);
There are no props in the object because the object contains a single array with a single object in the array.