how to post complex array to mvc c# api - c#

I'm trying to post an array tat one of it's members (th) is an array of strings, I stringify the array, here is hob it looks stringified:
[{"id":"201669887","name":"אורה","Sunday":"1","Monday":"1","Tuesday":"1","Wednesday":"0","Thursday":"1","Friday":"1","Sunday1":"1","Monday1":"1","Tuesday1":"1","Wednesday1":"0","Thursday1":"1","Friday1":"0","totalWorkHour":9,"th":["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"year":" ","schoolName":null,"schoolNumber":null},{"id":"201669887","name":"חנה","Sunday":"1","Monday":"1","Tuesday":"1","Wednesday":"0","Thursday":"1","Friday":"1","Sunday1":"1","Monday1":"1","Tuesday1":"1","Wednesday1":"0","Thursday1":"1","Friday1":"0","totalWorkHour":9,"th":["","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""]
I have a model in Mvc:
public class teachersExcelDataModel
{
.....
public int Thursday1 { get; set; }
public int Friday1 { get; set; }
public int totalWorkHour { get; set; }
public List<string> th { get; set; }
public string schoolName { get; set; }
public int schoolNumber { get; set; }
public string month { get; set; }
public string year { get; set; }
public teachersExcelDataModel()
{
th = new List<string>();
}
}
here is how i send it:
this.http.post(this.accessPointUrl3, JSON.stringify(this.sendData), { headers: this.headers }).subscribe(
noteRecord => {
if (noteRecord)
this.a = true;
}
);
and here is how I get it:
public void PostExportExcel([FromBody]List<teachersExcelDataModel>json)
but it comes null,
if i get it as object[], it;s okay,
where am i wrong?

Your example JSON string is not in correct format.
After fixing the format of the json, you will see that you are trying to parse schoolNumber field to integer, which in your case is null and I guess internally the framework throws exception.
Trying to parse the data to object[] does not require parsing null to integer, so now you know why it works in this case

the json format is incorrect based on what i can see from the question. missing "}" and "]" too.

Related

Convert Encoding.ASCII.GetString to Class Model in C#

I am trying to encode a 200+ byte-size word payload (Using M2MQTT) into a Dynamic variable and thereafter convert the encoded string (Dynamic variable) into a JSON object so that it can be mapped to its corresponding Class object so that it can be saved in a SQL Database.
//C#
private void MqttClient_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
var message = Encoding.ASCII.GetString(e.Message);
JObject? jsonMessage = JObject.Parse(message);
DataClass? classList= JsonConvert.DeserializeObject<DataClass>((string)jsonMessage);
AddMyItem(classList);
}
public void AddMyItem(DataClass? passedClassList)
{
using (var context = new DataClassDbContext())
{
context.DataClass.Add(passedClassList);
context.SaveChanges();
}
}
Typical Message Format
[{"sn":1027,"nodeId":"n1","MemberData1":1,"MemberData2":2,"MemberData3":3,"MemberData4":4,"MemberData5":5,"MemberData6":6,"MemberData7":7,"MemberData8":8,"MemberData9":9}]
But I am currently stuck at the conversion of message (Dynamic string variable) into a JSON object in order to pass it to classList for Class Model remapping - Not too sure what's the best syntax to implement for this.
The end goal is to map message's member value into a Class object of DataClass but of course, there is an implicit conversion type error when trying to pass the values directly, i.e., vFarm vFarmCo2PdList = message;. Hence, I am wondering if I need to process message variable in some way first.
Your example message indicated that it's collection of entries of type DataClass, which after conversion looks like this:
public class DataClass
{
public int sn { get; set; }
public string nodeId { get; set; }
public int MemberData1 { get; set; }
public int MemberData2 { get; set; }
public int MemberData3 { get; set; }
public int MemberData4 { get; set; }
public int MemberData5 { get; set; }
public int MemberData6 { get; set; }
public int MemberData7 { get; set; }
public int MemberData8 { get; set; }
public int MemberData9 { get; set; }
}
Having said that, you need to try deserializa it to DataClass[], which is array. I also suggest using System.Text.Json library, which is already shipped with .NET :)
Also, you do not need to create JObject. just deserialize from string, like this:
var o = JsonSerializer.Deserialize<DataClass[]>(message);

Convert JSON string to object C#

I have JSON string results as follows.
In this response Sometimes sizeKey and sizeName properties are returned as a string. But sometimes both properties are returns inside an array as follows
I am using following code to convert it to object
var assets = jObject["assets"].Children().ToList();
foreach (var item in assets)
{
decorationAssets.Add(item.ToObject<AEDecorationAssets>());
}
And my AEDecorationAssets class is as follows.
public class AEDecorationAssets
{
public string Id { get; set; }
public string Url { get; set; }
public string[] Colors { get; set; }
public string FontKey { get; set; }
public string SizeKey { get; set; }
public string ViewKey { get; set; }
public string FontName { get; set; }
public int Rotation { get; set; }
public string SizeName { get; set; }
public string TextValue { get; set; }
public string EntityType { get; set; }
public string LocationCode { get; set; }
public string LocationName { get; set; }
public string TextEffectKey { get; set; }
public string TextEffectName { get; set; }
public string DecorationMethod { get; set; }
public string NumDecorationColors { get; set; }
}
At the time when "sizeKey" is an array, the above code gives an error. How can I resolve this issue? Is there any JSON property we can use to resolve it?
One way you can do it is by making your SizeKey type an object (i.e. public object SizeKey { get; set; }), then you can switch/case on item.ToObject<AEDecorationAssets>().SizeKey.GetType() to figure out how to handle it (i.e. if String do this, if JArray do that), etc.
If a JSON type is sometime an array, and sometimes a string, you can't really map it simply to a .NET type, as there is none that supports this behavior.
So first you need a datatype that can store this, like and string[] or List<string>.
It could be that JsonConvert will solve this automatically, but otherwise you'll need to write a custom ContractResolver or JsonConverter. Here you can detect if the source property is a string or array. If it's an array, you can use the default deserialization. If it is a string, you need to convert it to an array with a single value.
Simply get json result for which you want to create c# object and then you can valid json response from https://jsonlint.com/ and then you can create c# object of any type json response which you want through http://json2csharp.com. And after get c# object of your json response you only need to deserialization of your json response to c# object which you have created. which will return you expected result.

JSON Deserializer "loses" last property of JSON value

passing a Json value like this one(this will be the var jsonValue in code):
"{\"Something\":0,\"Something2\":10,\"Something3\":{\"Something4\":17,\"Something5\":38042,\"Something6\":38043,\"Id\":215},\"Something7\":215,\"SomethingId\":42,\"Something8\":\"AString, Gläser\",\"Something8\":\"44-55-18\",\"Status\":{\"Caption\":\"Fixed\",\"Value\":7},\"Type\":\"Article\",\"Id\":97,\"#Delete\":true,\"Something9\":\"8\"}"
to the following code:
var deserializer = new JsonSerializer();
const string regex = #"/Date\((.*?)\+(.*?)\)/";
var reader = new JsonTextReader(new StringReader(jsonValue));
returnValue = deserializer.Deserialize(reader, type);
type is the typeof https://dotnetfiddle.net/LMPEl0 (thank you Craig) (sorry for the weird names, can't disclose the actual ones...)
The jsonvalue is generated by input in an editable cell of a DataTable and apparently places previously null values in the end of the json string.
I get a null value in the "Something9" property in the returnValue, instead of 8(Something9 was null before and set to 8 through an editable Cell of a DataTable)
Is there some problem with the Json value that I can't see?
Or do I need some setting in the Deserializer?
Thanks
You don't show what your type is so I generated one using http://json2csharp.com.
public class Something3
{
public int Something4 { get; set; }
public int Something5 { get; set; }
public int Something6 { get; set; }
public int Id { get; set; }
}
public class Status
{
public string Caption { get; set; }
public int Value { get; set; }
}
public class RootObject
{
public int Something { get; set; }
public int Something2 { get; set; }
public Something3 Something3 { get; set; }
public int Something7 { get; set; }
public int SomethingId { get; set; }
public string Something8 { get; set; }
public Status Status { get; set; }
public string Type { get; set; }
public int Id { get; set; }
[JsonProperty("#Delete")]
public bool Delete { get; set; }
public string Something9 { get; set; }
}
Because one of your properties has a name that is not valid as a .NET property I added the [JsonProperty] attribute to that one. After that it worked perfectly. Perhaps the problem is with how you declared the #Delete JSON property in your .NET type. Given that Something9 comes after that property it would be my guess that that's part of the problem.
Here's the fiddle.
https://dotnetfiddle.net/McZF9Q
While Craig's answer helped a lot and finally led to a solution the exact answer to the problem was the following:
The Status object is an Enum and was not Deserialized correctly.
Due to that, anything that followed in the Json string was also not deserialized.
Implementing a custom Enum Deserializer was the solution. There are other Questions in stackoverflow that helped with this, particularly this one here:
How can I ignore unknown enum values during json deserialization?
Thank you everyone :)

Can't deserialize json football data

I want to create an Windows Forms application that uses data from football-data.org. This is my first time I'm working with restful/JSON and I'm stuck.
When I try to get all of the leagues that football-data.org provides this is the response you get from the football-data.org api : response
I use the following code to get all of the data correct:(lbResultBox is a listbox)
private void btAllLeagues_Click(object sender, EventArgs e)
{
lbResultBox.Items.Clear();
List<Leagues> LL = GetLeagues("soccerseasons");
foreach (var item in LL)
{
lbResultBox.Items.Add(item.caption);
}
}
public static List<Leagues> GetLeagues(string endurl)
{
var syncClient = new WebClient();
var content = syncClient.DownloadString(baseurl + endurl);
return JsonConvert.DeserializeObject<List<Leagues>>(content);
}
public class Leagues
{
public IDictionary<string,LeagueLinks> _links { get; set; }
public string caption { get; set; }
public string league { get; set; }
public string year { get; set; }
public string numberOfTeams { get; set; }
public string numberOfGames { get; set; }
public string lastUpdated { get; set; }
}
public class LeagueLinks
{
public string href { get; set; }
}
This works.
But when I try to get all the teams from a league this is the response i get from the api. I use this code:
private void btAllTeams_Click(object sender, EventArgs e)
{
List<LeagueTeams> LT = GetLeagueTeams("soccerseasons/" + id + "/teams");
}
public static List<LeagueTeams> GetLeagueTeams(string endurl)
{
var syncClient = new WebClient();
var content = syncClient.DownloadString(baseurl + endurl);
return JsonConvert.DeserializeObject<List<LeagueTeams>>(content);
}
public class LeagueTeams
{
public IDictionary<string, LeagueLinks> _links { get; set; }
public string count { get; set; }
public IDictionary<string, LeagueTeam> teams { get; set; }
}
public class LeagueTeam
{
public IDictionary<string, TeamLinks> _links { get; set; }
public string name { get; set; }
public string code { get; set; }
public string shortName { get; set; }
public string squadMarketValue { get; set; }
public string crestUrl { get; set; }
}
public class TeamLinks
{
public string href { get; set; }
}
But i get the following error:
An unhandled exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll
Additional information: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type System.Collections.Generic.IDictionary`2[System.String,FootballTestApplication.LeagueTeam]' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
When i look at what the api give's me for response I can see a difference in how the response begins. With collecting all of the leagues it starts and ends with brackets ([]) but when collecting the teams in a league it doesn't start or end with brackets. When I Add the brackets myself I still get the error. This is how I add the brackets:
return JsonConvert.DeserializeObject<List<LeagueTeams>>("["+content+"]");
What am I doing wrong here?
The problem lies in the fact that the JSON returned is NOT an Array, List, Dictionary or other Enumerable but is instead an object of it's own.
If we take your JSON from that API link and go through it element by element, we learn that your Type is wrong.
You tell the JSON Serializer that the root object is a List<LeagueTeams>, but it is not. It is in fact a single LeagueTeams object.
If we make that modification to the deserializer, and we make a couple modifications to your LeagueTeams class (mostly the fact that you were deserializing the links property wrong), you are all set:
public class LeagueTeams
{
public List<IDictionary<string, string>> _links { get; set; }
public string count { get; set; }
public List<LeagueTeam> teams { get; set; }
}
return JsonConvert.DeserializeObject<LeagueTeams>(content);
I've attached an image of the results.
Additional Notes
Another thing to note: the JSON to C# website (http://json2csharp.com/) does NOT handle this JSON correctly, it in fact generates an object that is almost correct, but not quite. (Though, the generated object will still work properly, it is not an entirely correct mapping of the input JSON.) This is due, in part, to the fault of the generator, but also the website. It attempts to generate a list of a two-property Link element for the root links item, where it instead should have used a list of a dictionary to get correct mappings. (Though, this is a bit befuddling, it is the most correct approach.) Another thing to keep into consideration, yes, it does fine for getting a good start, but generally speaking, proper JSON handling requires more meticulous inspection of the generated objects to guarantee correctness.

parsing nested (I think) JSON

I've been trying to parse this JSON string. I'm using JSON.NET and a snippet of the JSON, my classes and basic function calls follow:
{"status":"ok","apirate":"0","people":{
"Mike":{"id":"Mike","rating":"0.80","questions":"100"},
"Donald":{"id":"Donald","rating":"0.7","questions":"9"},
"Tony":{"id":"Tony","rating":"0.22","questions":"2"},
"Penelope":{"id":"Penelope","rating":"0.006","questions":"6"},
"Sarah":{"id":"Sarah","rating":"0.79","questions":"20"},
"Thomas":{"id":"Thomas","rating":"0.12","questions":"25"},
"Gail":{"id":"Gail","rating":"0.44","questions":"35"}}}
The classes I'm using as storage objects:
public class Folks
{
public Folks()
{
}
public String status;
public String message; //optional
public int apirate;
public PeopleDetails[] people;
}
public class PeopleDetails
{
public PeopleDetails ()
{
}
public String id;
public double rating;
public int questions;
}
And finally, what I'm doing in the code:
Folks test = new Folks();
test = JsonConvert.DeserializeObject<Folks>(myRequest.GetResponse());
Status and API rate are coming through fine, message doesn't exist because there's no error and my PeopleDetails array is making an exception. (EDIT: throwing a JsonSerializationException because the type requires a JSON array to deserialize correctly.) I've tried putting another class/object between the two I've pasted here and I've tried different collections, and so on.
So... since this is my first time working with this (smart, pick the complex stuff the first time) can anybody point me towards a solution?
Thanks in advance.
Well, first, your given JSON is incorrect, there is a { missing in the penelope record.
so the correct JSON would be
{"status":"ok","apirate":"0","people":{
"Mike":{"id":"Mike","rating":"0.80","questions":"100"},
"Donald":{"id":"Donald","rating":"0.7","questions":"9"},
"Tony":{"id":"Tony","rating":"0.22","questions":"2"},
"Penelope":{"id":"Penelope","rating":"0.006","questions":"6"},
"Sarah":{"id":"Sarah","rating":"0.79","questions":"20"},
"Thomas":{"id":"Thomas","rating":"0.12","questions":"25"},
"Gail":{"id":"Gail","rating":"0.44","questions":"35"}}}
Then, if you have a look at the structur, you may not that people is not a list but a dictionary, with the name as the key.
So, here is a working test
[TestMethod]
public void Test()
{
var json = "{\"status\":\"ok\",\"apirate\":\"0\",\"people\":{\n\"Mike\":{\"id\":\"Mike\",\"rating\":\"0.80\",\"questions\":\"100\"},\n\"Donald\":{\"id\":\"Donald\",\"rating\":\"0.7\",\"questions\":\"9\"},\n\"Tony\":{\"id\":\"Tony\",\"rating\":\"0.22\",\"questions\":\"2\"},\n\"Penelope\":{\"id\":\"Penelope\",\"rating\":\"0.006\",\"questions\":\"6\"},\n\"Sarah\":{\"id\":\"Sarah\",\"rating\":\"0.79\",\"questions\":\"20\"},\n\"Thomas\":{\"id\":\"Thomas\",\"rating\":\"0.12\",\"questions\":\"25\"},\n\"Gail\":{\"id\":\"Gail\",\"rating\":\"0.44\",\"questions\":\"35\"}}}";
var folks = JsonConvert.DeserializeObject<Folks>(json);
Assert.AreEqual("ok", folks.Status);
}
public class Folks
{
public Folks()
{
this.People = new Dictionary<string, PeopleDetails>();
}
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("apirate")]
public int Apirate { get; set; }
[JsonProperty("people")]
public Dictionary<string, PeopleDetails> People { get; set; }
}
public class PeopleDetails
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("rating")]
public decimal Rating { get; set; }
[JsonProperty("questions")]
public int Questions { get; set; }
}

Categories