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);
Related
I'm having a well-defined class for sending as JSON body in an HTTP request.
public class EventData
{
public string deviceJobId { get; set; }
public int eventID { get; set; }
public long time_ms { get; set; }
/// similar fields
}
Now I have to add one more field called HealthInfo. The value of this new HealthInfo is a nested JSON read from some file.
The fields of this JSON file change from time to time, and there is no guarantee that some fields will always be present.
I don't want to read/modify any value of that and just need to publish this EventData as a json as part of an HTTP request.
Then how to add HealthInfo correctly?
I tried to put HealthInfo as string and object is getting double serialized.
you have to convert to JObject before you add new json string
JObject jo = JObject.FromObject(eventData);
jo["HealthInfo"] = jsonStringHealthInfo;
//or it could be (your question needs some details)
jo["HealthInfo"]=JObject.Parse(jsonStringHealthInfo);
StringContent content = new StringContent(jo.ToString(), Encoding.UTF8, "application/json");
var response = await client.PostAsync(api, content))
If you know all of the possible properties inside HealthInfo then you can create new class HealthInfo with nullable properties.
public class HealthInfo
{
public string? SomeData { get; set; }
public int? SomeOtherData { get; set; }
}
and then add nullable HealthInfo in your main class:
public class EventData
{
public string deviceJobId { get; set; }
public int eventID { get; set; }
public long time_ms { get; set; }
public HealthInfo? HealthInfo { get; set; }
/// similar fields
}
However if you're not sure what kind of data you're gonna get and want to avoid double serialization, just pass HealthInfo as object:
public class EventData
{
public string deviceJobId { get; set; }
public int eventID { get; set; }
public long time_ms { get; set; }
public object? HealthInfo { get; set; }
/// similar fields
}
You can use of C# reflection. (TypeBuilder.DefineProperty Method)
In fact you must add prop to the class in run time.
see full information at
https://learn.microsoft.com/
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.
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.
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.
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; }
}