My project has a 3rd party web API that returns a json string in the following format (including the starting and ending curly braces):
{
"866968030210604":{
"dt_server":"2019-02-07 12:21:27",
"dt_tracker":"2019-02-07 12:21:27",
"lat":"28.844968",
"lng":"76.858502",
"altitude":"0",
"angle":"154",
"speed":"9",
"params":{
"pump":"0",
"track":"1",
"bats":"1",
"acc":"0",
"batl":"4"
},
"loc_valid":"1"
},
"866968030221205":{
"dt_server":"2019-02-07 12:20:24",
"dt_tracker":"2019-02-07 12:19:41",
"lat":"28.845904",
"lng":"77.096063",
"altitude":"0",
"angle":"0",
"speed":"0",
"params":{
"pump":"0",
"track":"1",
"bats":"1",
"acc":"0",
"batl":"4"
},
"loc_valid":"1"
},
"866968030212030":{
"dt_server":"0000-00-00 00:00:00",
"dt_tracker":"0000-00-00 00:00:00",
"lat":"0",
"lng":"0",
"altitude":"0",
"angle":"0",
"speed":"0",
"params":null,
"loc_valid":"0"
}
}
I want to deserialize it into a c# class object for further processing. I made the following class structure for the same:
class Params
{
public string pump { get; set; }
public string track { get; set; }
public string bats { get; set; }
public string acc { get; set; }
public string batl { get; set; }
}
class GPSData
{
public string dt_server { get; set; }
public string dt_tracker { get; set; }
public string lat { get; set; }
public string lng { get; set; }
public string altitude { get; set; }
public string angle { get; set; }
public string speed { get; set; }
public Params ObjParams { get; set; }
public string loc_valid { get; set; }
}
and I am trying the following code to deserialize:
JavaScriptSerializer jSerObj = new JavaScriptSerializer();
List<GPSData> lstGPSData = (List<GPSData>)jSerObj.Deserialize(json, typeof(List<GPSData>));
But every time it is showing NULL values assigned to each property of the class after the Deserialize() method is called. Please help me on this.
Your json is not in list format so deserializing to List<> isn't work
So you need to deserialize it into Dictionary<string, GPSData> like
JavaScriptSerializer jSerObj = new JavaScriptSerializer();
Dictionary<string, GPSData> lstGPSData = (Dictionary<string, GPSData>)jSerObj.Deserialize(json, typeof(Dictionary<string, GPSData>));
Usage:
foreach (var item in lstGPSData)
{
string key = item.Key;
GPSData gPSData = item.Value;
}
Also, you can list all your GPSData from above dictionary like,
List<GPSData> gPSDatas = lstGPSData.Values.ToList();
Output: (From Debugger)
Related
I'm running into issues parsing a json reponse from GraphQL. The issue is the array will come back with more arrays half the time. My code is just getting out of hand and ugly.
Json file (trimmed it a bit. It can be 20+ data arrays)
{
"activity_logs": [
{
"data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":2165787062,\"pulse_name\":\"Tyler\",\"column_id\":\"email_address\",\"column_type\":\"email\",\"column_title\":\"Email Address\",\"value\":{\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"previous_value\":{\"email\":\"tyler#email.com\",\"text\":\"tyler#email.com\",\"changed_at\":\"2022-02-15T21:18:48.297Z\",\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"is_column_with_hide_permissions\":false,\"previous_textual_value\":\"tyler#email.com\"}"
},
{
"data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":216578711,\"pulse_name\":\"Nicholas \",\"column_id\":\"email_address\",\"column_type\":\"email\",\"column_title\":\"Email Address\",\"value\":{\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"previous_value\":{\"email\":\"nicholas#email.com\",\"text\":\"nicholas#email.com\",\"changed_at\":\"2022-02-16T04:44:52.046Z\",\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"is_column_with_hide_permissions\":false,\"previous_textual_value\":\"nicholas#email.com\"}"
},
{
"data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":216578711,\"pulse_name\":\"Nicholas \",\"column_id\":\"batch_5\",\"column_type\":\"text\",\"column_title\":\"Batch #\",\"value\":{\"value\":\"75\"},\"previous_value\":{\"value\":\"74\"},\"is_column_with_hide_permissions\":false}"
},
{
"data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"pulse_id\":216578711,\"is_top_group\":false,\"value\":{\"name\":\"Nicholas \"},\"previous_value\":{\"name\":\"Nicholas \"},\"column_type\":\"name\",\"column_title\":\"Name\"}"
}
]
}
Random "get it to work" attempt after giving up on making is a List based on a Class. The IContainers within IContainers were getting very complex.
var responseData = JObject.Parse(responseText).SelectToken("data").SelectToken("boards").SelectToken("activity_logs");
dynamic updatedRecords = JsonConvert.DeserializeObject(responseData.ToString());
foreach (var record in updatedRecords)
{
List<Dictionary<string, string>> records = new List<Dictionary<string, string>>();
Dictionary<string, string> fields = new Dictionary<string, string>();
dynamic updates = JsonConvert.DeserializeObject(JObject.Parse(record.ToString()).SelectToken("data").ToString());
foreach(var update in updates)
{
switch (update.Name.ToString())
{
case "column_id":
fields.Add(update.Name.ToString(), update.Value.ToString());
break;
case "pulse_name":
fields.Add(update.Name.ToString(), update.Value.ToString());
break;
case "value":
dynamic values = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
if (update.Name.ToString().Contains("column_settings"))
{
foreach (var value in values)
{
dynamic columns = JsonConvert.DeserializeObject(JObject.Parse(value.Value.ToString()));
foreach(var column in columns)
{
fields.Add($"Value_{column.Name.ToString()}", column.Value.ToString());
}
}
}
else
{
foreach (var value in values)
{
fields.Add($"Value_{value.Name.ToString()}", value.Value.ToString());
}
}
break;
case "previous_value":
dynamic prevValues = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
foreach (var prevalue in prevValues)
{
fields.Add($"Prevalue_{prevalue.Name.ToString()}", prevalue.Value.ToString());
}
break;
case "previous_textual_value":
fields.Add(update.Name.ToString(), update.Value.ToString());
break;
}
}
if (fields.Count > 0)
{
records.Add(fields);
fields.Clear();
}
}
My Error when I get to:
dynamic values = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
- $exception {"The best overloaded method match for 'Newtonsoft.Json.JsonConvert.DeserializeObject(string)' has some invalid arguments"} Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
Solution is a big help and led to my answer. The issue is the activity_logs data comes with escape characters in it so the string contains \\".
I had to format the data sections with Replace("\\", "") and Replace("\"{", "{") and Replace("}\""), "}"). This made the string readable as a Json file.
You have to pass in a string to DeserializeObject instead of a JSON object.
Another way would be get your JSON mapped to a POCO types as follows, easy way to do is on Visual Studio (Copy your JSON contents, on Visual Studio create a new empty class -> Edit-> Past Special -> Paste JSON as classes)
public class LogsRoot
{
public Activity_Logs[] activity_logs { get; set; }
}
public class Activity_Logs
{
public string data { get; set; }
}
public class DataRoot
{
public long board_id { get; set; }
public string group_id { get; set; }
public bool is_top_group { get; set; }
public long pulse_id { get; set; }
public string pulse_name { get; set; }
public string column_id { get; set; }
public string column_type { get; set; }
public string column_title { get; set; }
public Value value { get; set; }
public Previous_Value previous_value { get; set; }
public bool is_column_with_hide_permissions { get; set; }
public string previous_textual_value { get; set; }
}
public class Value
{
public Column_Settings column_settings { get; set; }
}
public class Column_Settings
{
public bool includePulseInSubject { get; set; }
public bool ccPulse { get; set; }
public string bccList { get; set; }
}
public class Previous_Value
{
public string email { get; set; }
public string text { get; set; }
public DateTime changed_at { get; set; }
public Column_Settings1 column_settings { get; set; }
}
public class Column_Settings1
{
public bool includePulseInSubject { get; set; }
public bool ccPulse { get; set; }
public string bccList { get; set; }
}
Then load the JSON and manipulate as follows,
var json = File.ReadAllText("data.json");
var rootLogs = JsonConvert.DeserializeObject<LogsRoot>(json);
Dictionary<string, string> fields = new Dictionary<string, string>();
foreach (var logJson in rootLogs.activity_logs)
{
var log = JsonConvert.DeserializeObject<DataRoot>(logJson.data);
fields.Add(log.column_id, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
fields.Add(log.pulse_name, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
fields.Add(log.previous_value.email, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
fields.Add(log.previous_textual_value, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
}
This might not solve all your issues, but for the specific exception you are running into, it is because you are trying to deserialize a JObject instead of string.
Probably you just want:
dynamic values = JsonConvert.DeserializeObject(update.Value.ToString());
using MessagePack;
[MessagePackObject]
public class CPegar_ids
{
[Key(0)]
public string operationName { get; set; }
[Key(1)]
public Variables variables { get; set; }
[Key(2)]
public string query { get; set; }
}
[MessagePackObject]
public class Variables
{
[Key(0)]
public object activeType { get; set; }
[Key(1)]
public string[] instruments { get; set; }
[Key(2)]
public string leverageInstrument { get; set; }
[Key(3)]
public int userGroupID { get; set; }
[Key(4)]
public string sortField { get; set; }
[Key(5)]
public string sortDirection { get; set; }
[Key(6)]
public int limit { get; set; }
[Key(7)]
public int offset { get; set; }
}
string json_data = #"
{
""operationName"": ""GetAssets"",
""variables"": {
""activeType"": null,
""instruments"": [
""BinaryOption"",
""DigitalOption"",
""FxOption"",
""TurboOption""
],
""leverageInstrument"": ""BinaryOption"",
""userGroupID"": 193,
""sortField"": ""Name"",
""sortDirection"": ""Ascending"",
""limit"": 20,
""offset"": 0
},
""query"": """"
}
";
var ob_ids = MessagePackSerializer.Deserialize<CPegar_ids>(Encoding.UTF8.GetBytes(json_data ));
Console.WriteLine($" IDS OB: {ob_ids.GetType()}");
https://github.com/neuecc/MessagePack-CSharp
I'm downloading JSON with HttpWebRequest, which returns a var string. I want to use this string to Deserialize with MessagePackSerializer. I've tried several different ways, with Utf8Json I can do it, but with this MessagePack I can't. I want to use MessagePack because it is much faster.
It looks like MessageBack have their own notation which is not JSON. But you're trying to deserialize Json into their custom notation which fails for obvious reasons. They seem to keep it small an compact by using more unicode in place of standard characters like JSON.
see https://msgpack.org/index.html
This is why you're not going to make it work putting in a JSON string and trying to deserialize it. If you're looking for faster JSON options there are a few other common alternatives to Newtonsoft Json.NET such as fastJSON https://github.com/mgholam/fastJSON
Reversing your sample code we can get an example of what the serialized values look like:
var myObject = new CPegar_ids {
operationName = "GetAssets",
variables = new Variables {
activeType = null,
instruments = new string[] {
"BinaryOption",
"DigitalOption",
"TurboOption"
},
leverageInstrument = "BinaryOption",
userGroupID = 193,
sortField = "Name",
sortDirection = "Ascending",
limit = 20,
offset = 0
},
query = ""
};
var bytes = MessagePackSerializer.Serialize(myObject);
Console.WriteLine(Encoding.UTF8.GetString(bytes));
the output of which is:
��operationName�GetAssets�variables��activeType��instruments��BinaryOption�DigitalOption�TurboOption�leverageInstrument�BinaryOption�userGroupID���sortField�Name�sortDirection�Ascending�limit14�offset00�query�
I couldn't find a good explanation on why it is not working. But there is a way to make it work instead of using Key(int index) attribute we will use Key(string propertyName) attribute.
Should you use an indexed (int) key or a string key? We recommend
using indexed keys for faster serialization and a more compact binary
representation than string keys. Reference.
OBJECTS
[MessagePackObject]
public class CPegar_ids
{
[Key("operationName")]
public string operationName { get; set; }
[Key("variables")]
public Variables variables { get; set; }
[Key("query")]
public string query { get; set; }
}
[MessagePackObject]
public class Variables
{
[Key("activeType")]
public object activeType { get; set; }
[Key("instruments")]
public string[] instruments { get; set; }
[Key("leverageInstrument")]
public string leverageInstrument { get; set; }
[Key("userGroupID")]
public int userGroupID { get; set; }
[Key("sortField")]
public string sortField { get; set; }
[Key("sortDirection")]
public string sortDirection { get; set; }
[Key("limit")]
public int limit { get; set; }
[Key("offset")]
public int offset { get; set; }
}
SERIALIZATION
var jsonByteArray = MessagePackSerializer.ConvertFromJson(File.ReadAllText("json1.json"));
CPegar_ids ob_ids = MessagePackSerializer.Deserialize<CPegar_ids>(jsonByteArray);
I am using this code to read a json file firstSession.json and display it on a label.
var assembly = typeof(ScenarioPage).GetTypeInfo().Assembly;
string jsonFileName = "firstSession.json";
Stream stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{jsonFileName}");
using (var reader = new StreamReader(stream))
{
var json = reader.ReadToEnd(); //json string
var data = JsonConvert.DeserializeObject<SessionModel>(json);
foreach (SessionModel scenario in data)
{
scenarioName.Text = scenario.title;
break;
}
scenarioName.Text = data.title; // scenarioName is the name of the label
}
SessionModel.cs looks like:
public class SessionModel : IEnumerable
{
public int block { get; set; }
public string name { get; set; }
public string title { get; set; }
public int numberMissing { get; set; }
public string word1 { get; set; }
public string word2 { get; set; }
public string statement1 { get; set; }
public string statement2 { get; set; }
public string question { get; set; }
public string positive { get; set; } // positive answer (yes or no)
public string negative { get; set; } // negative answer (yes or no)
public string answer { get; set; } // positive or negative
public string type { get; set; }
public string format { get; set; }
public string immersion { get; set; }
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
}
The beginning of my json is:
{
"firstSession": [
{
"block": 1,
"name": "mark",
"title": "mark's house",
"numberMissing": 1,
"word1": "distracted",
"word2": "None",
"statement1": "string 1",
"statement2": "None",
"question": "question",
"positive": "No",
"negative": "Yes",
"answer": "Positive",
"type": "Social",
"format": "Visual",
"immersion": "picture"
},
I am getting a Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object into type "MyProject.SessionModel" because the type requires a JSON array to deserialize correctly. To fix this error either change the JSON to a JSON array or change the deserialized type so that it is a normal .NET type that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'firstSession', line 2, position 17.
How can I convert the json string to a json array? Or make one of the other modifications the debugger suggests?
you need to create a wrapper class (json2csharp.com will help you do this)
public class Root {
public List<SessionModel> firstSession { get; set; }
}
then
var data = JsonConvert.DeserializeObject<Root>(json);
data.firstSession will be a List<SessionModel>
Create a new Class and have firstSession as List of SessionModel.
public class Sessions
{
public List<SessionModel> firstSession { get; set; }
}
Remove IEnumerable from the SessionModel
public class SessionModel
{
public int block { get; set; }
public string name { get; set; }
public string title { get; set; }
}
Change thedeserialization part as follows
var data = JsonConvert.DeserializeObject(line);
foreach (SessionModel scenario in data.firstSession)
{
//Here you can get each sessionModel object
Console.WriteLine(scenario.answer);
}
I am giving up on this.
I've got the following Json that I need to deserialize:
json = "{
"2018-05-21": {
"lastUpdate": "2018-05-21 01:00:05",
"stops": [
{
"stopId": 1838,
"stopCode": "02"
}, {
"stopId": 1839,
"stopCode": "08"
}]}}";
var deserialized = JsonConvert.DeserializeObject<StopDate>(json); // null
and those classes:
public class StopDate
{
public BusStop date { get; set; }
}
public class BusStop
{
public string LastUpdate { get; set; }
public Stop[] Stops { get; set; }
}
public class Stop
{
public int StopId { get; set; }
public string StopName { get; set; }
}
The problem is that deserialized variable is null.
Apart from the overall ugliness when it comes to the names etc, I'd like it to be up and running just for a good start. All help's appreciated.
Convert the JSON to a Dictionary<DateTime, BusStop>
var deserialized = JsonConvert.DeserializeObject<Dictionary<DateTime, BusStop>>(json);
The DateTime key of the dictionary maps to the date in the JSON.
If the DateTime causes any issue then use a string as the key, ie Dictionary<string, BusStop> where the key can be parsed into a DateTime is needed
var deserialized = JsonConvert.DeserializeObject<Dictionary<string, BusStop>>(json);
BusStop busStop = deserialized["2018-05-21"];
And you probably want to make LastUpdate a DateTime rather than a string (as suggested by a commenter)
public class BusStop {
public DateTime LastUpdate { get; set; }
public Stop[] Stops { get; set; }
}
public class Stop {
public int StopId { get; set; }
[JsonProperty("stopCode")]
public string StopName { get; set; }
}
Im having with the content. it is auto increment.
the result is static but the content is dynamic.
I'm using a hardcoded array in catching the return string from the web. Can anyone json decoder in converting the returned string to c# object
This is the returned string from web:
{
"result":{
"count":"3"
},
"content_1":{
"message_id":"23",
"originator":"09973206870",
"message":"Hello",
"timestamp":"2016-09-14 13:59:47"
},
"content_2":{
"message_id":"24",
"originator":"09973206870",
"message":"Test again.",
"timestamp":"2016-09-14 14:49:14"
},
"content_3":{
"message_id":"25",
"originator":"09973206870",
"message":"Another message",
"timestamp":"2016-09-14 14:49:20"
}
}
On site json2csharp.com you can generate classes for JSON data.
Generated classes needs some improvements and can look like:
public class Result
{
public string count { get; set; }
}
public class Content
{
public string message_id { get; set; }
public string originator { get; set; }
public string message { get; set; }
public string timestamp { get; set; }
}
public class RootObject
{
public Result result { get; set; }
public Content content_1 { get; set; }
public Content content_2 { get; set; }
public Content content_3 { get; set; }
}
And using JSON.NET you can deserialize it:
public class Program
{
static public void Main()
{
string json = "{ \"result\":{ \"count\":\"3\" }, \"content_1\":{ \"message_id\":\"23\", \"originator\":\"09973206870\", \"message\":\"Hello\", \"timestamp\":\"2016-09-14 13:59:47\" }, \"content_2\":{ \"message_id\":\"24\", \"originator\":\"09973206870\", \"message\":\"Test again.\", \"timestamp\":\"2016-09-14 14:49:14\" }, \"content_3\":{ \"message_id\":\"25\", \"originator\":\"09973206870\", \"message\":\"Another message\", \"timestamp\":\"2016-09-14 14:49:20\" } }";
RootObject ro = JsonConvert.DeserializeObject<RootObject>(json);
Console.WriteLine(ro.content_1.message_id);
Console.WriteLine(ro.content_2.message_id);
}
}