C# json deserialize object - c#

I am new with C#, and so I don't know too much about it. I want to deserialize json object, but I am having some issues.
Thi is json object:
var json = "[{
"idSite":"1",
"visitorId":"a393fed00271f588",
"actionDetails":[{
"type":"action",
"url":"http:\/\/mysite.info\/test-24\/",
"customVariables":{
"1":{
"customVariablePageName1":"URL",
"customVariablePageValue1":"http:\/\/mysite.info\/p"
}
},
"timeSpent":"78",
}]
}]";
And I am trying to deserialize it on this way:
var visits = JsonConvert.DeserializeObject<VisitorDetails[]>(json);
public class VisitorDetails
{
public string idSite { get; set; }
public string visitorId { get; set; }
public List<ActionDetail> actionDetails { get; set; }
}
public class ActionDetail
{
public string type { get; set; }
public string url { get; set; }
public string timeSpent { get; set; }
public object customVariables { get; set; }
}
Everything is fine, except "customVariables" in "ActionDetails" it just set it to object with one value as string:
{
"1":{
"customVariablePageName1":"URL",
"customVariablePageValue1":"http:\/\/mysite.info\/p"
}
}
It doesn't deserialize it at all.
I need this deserialize so I can say:
foreach (var visit in Model.PiwikInfo)
{
#foreach (var action in visit.actionDetails)
{
#if (action.customVariables != null && action.customVariables.Any())
{
foreach (var cv in visit.customVariables.Where(cv => cv.HasProperty("customVariablePageName1")))
{
<span>URL: #cv.GetProperty("customVariablePageValue1")</span>
}
}
}
}

Well, this happens, because you have specified that the customVariables member is of type System.Object. So deserialization will result in assigning it the string value.
So lets try to mold it into a shape that better resembles the input JSON structure and your specific use of the deserialization result, in two steps, by changing the type declaration of the customVariables member variable, and inspecting its deserialized content after each change.
Make it a dictionary:
public Dictionary<string, object> customVariables { get; set; }
This will result in a dictionary that contains a single element with the key "1" and a single string value:
{
"customVariablePageName1": "URL",
"customVariablePageValue1": "http://mysite.info/p"
}
Make it a dictionary of dictionaries:
public Dictionary<string, Dictionary<string, string>> customVariables { get; set; }
And print its deserialized ouput like this:
var visits = JsonConvert.DeserializeObject<VisitorDetails[]>(json_string);
foreach (var visit in visits)
{
Console.WriteLine("Visitor: {0}", visit.visitorId);
foreach (var detail in visit.actionDetails)
{
Console.WriteLine(" Action: {0}", detail.type);
foreach (var cv in detail.customVariables.Where(x => x.Value.ContainsKey("customVariablePageName1")))
{
Console.WriteLine(" Custom variable #{0}", cv.Key);
Console.WriteLine(" Value: {0}", cv.Value["customVariablePageValue1"]);
}
}
}
Which resembles your view's foreach, and will produce the following output:
Visitor: a393fed00271f588
Action: action
Custom variable #1
Value: http://mysite.info/p

Since I can't still comment I will have to post this as an answer. have you tried using the built in function of C#?
See Here
Also, from what I gather, on the Documentation of that method it converts it converts the json into a system object.
Also, from the looks of it it seems like the customVariables segment is either an array or a broken object. I say that because it is missing the square brackets like in the previous declarations, making it look like:
...
"customVariables":[{
"1":[{
"customVariablePageName1":"URL",
"customVariablePageValue1":"http:\/\/mysite.info\/p"
}]
}],
...
Hope it helps.

try this structure
public class T1
{
public string customVariablePageName1 { get; set; }
public string customVariablePageValue1 { get; set; }
}
public class CustomVariables
{
public T1 t1 { get; set; }
}
public class ActionDetail
{
public string type { get; set; }
public string url { get; set; }
public CustomVariables customVariables { get; set; }
public string timeSpent { get; set; }
}
public class RootObject
{
public string idSite { get; set; }
public string visitorId { get; set; }
public List<ActionDetail> actionDetails { get; set; }
}

Related

C# Parsing Json string returned from GraphQL - Monday.com

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());

Getting NULL values while deserializing complex json

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)

Unable to parse JSON with empty array/objects

Trying the parse this json file and it seems to be getting stuck on empty objects and arrays.
{"Unexpected character encountered while parsing value: [. Path 'notes'."}
{
"id":null,
"phone":null,
"name":" ",
"email":null,
"address":null,
"assignee":null,
"notes":[
],
"created_at":null,
"items":{
"0":{
"minimized":false,
"sku":{
"partner_id":null,
"type_id":0,
"errors":{
}
}
}
}
}
CLASSES
public class RootObject
{
public string id { get; set; }
public string phone { get; set; }
public string name { get; set; }
public string email { get; set; }
public string address { get; set; }
public string assignee { get; set; }
public string notes { get; set; }
public string created_at { get; set; }
public Items items { get; set; }
}
public class Items
{
public bool minimized { get; set; }
public Sku sku { get; set; }
}
public class Sku
{
public int partner_id { get; set; }
public int type_id { get; set; }
public Errors errors { get; set; }
}
public class Errors
{
}
The issue appears to be with handling the Notes and Errors property, I've tried to use the following settings as per a few other SO posts but nothing has worked and I am not sure how to get this to deserialize into an object.
RootObject o = JsonConvert.DeserializeObject<RootObject>(json, new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
});
Perhaps someone can help me out because it seems to me JSON.net should be able to handle these properties?
Here's a working dotNetFiddle: https://dotnetfiddle.net/Lnkojw
Here's the output.
NOTE: I put in sample values in your json for your null values so you can see that it is working)
Your class definitions (autogenerated from http://json2csharp.com/ ) need to be modified as shown below.
public class RootObject
{
public string id { get; set; }
public string phone { get; set; }
public string name { get; set; }
public string email { get; set; }
public string address { get; set; }
public string assignee { get; set; }
public List<string> notes { get; set; }
public string created_at { get; set; }
public Dictionary<int,Item> items { get; set; }
}
public class Item
{
public bool minimized { get; set; }
public Sku sku { get; set; }
}
public class Sku
{
public int partner_id { get; set; }
public int type_id { get; set; }
[JsonIgnore]
public object errors { get; set; }
}
Since you have stated in comments that Errors will always be empty, I removed that redundant Errors class you had, with no properties or members. I also set the errors member in the Sku class to be object type in case you get values in future. Finally I set this errors property to [JsonIgnore] so json.net will ignore it for serialization / deserialization
Also Items appears to be Dictionary with an int for key and an Item for Value. So I have changed the definition there also.
Here's the code that deserializes and prints out the values.
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
string json = #"{
""id"":1,
""phone"":""415-000-1234"",
""name"":"" "",
""email"":null,
""address"":null,
""assignee"":null,
""notes"":[
],
""created_at"":null,
""items"":{
""0"":{
""minimized"":false,
""sku"":{
""partner_id"":21,
""type_id"":44,
""errors"":{
}
}
}
}
}";
Console.WriteLine("Deserializing json...");
RootObject o = JsonConvert.DeserializeObject<RootObject>(json, new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
});
Console.WriteLine("Success!");
Console.WriteLine("id #: {0}",o.id);
Console.WriteLine("phone #: {0}",o.phone);
foreach (var item in o.items)
{
Console.WriteLine(" Item #: {0}",item.Key);
if (item.Value != null)
{
Console.WriteLine(" SKU: partner_id: {0}",item.Value.sku.partner_id);
Console.WriteLine(" SKU: type_id: {0}",item.Value.sku.type_id);
}
}
}
}
And once again, here's the output. You can see the json values properly deserialized.
PRO TIPS:
Use a sample json that has values for as many fields as possible, so that http://json2csharp.com/ can generate the proper classes
Whenever you have a nameless property like the items in your json,you will likely need to inspect what http://json2csharp.com/ generated and modify it to be a Dictionary or a NameValuePair or KeyValuePair or something else. It is on a case by case basis. In other words, for 99% of well designed json, you can "plug and play" with http://json2csharp.com/ , for the remaining 1% you will have to customize the classes generated, or your serialization code or both.
The issue seems to be that in your auto-properties for RootObject, you have the notes property listed as a string rather than string[] - if notes are indeed an array of strings, your JSON snippet doesn't show that.
You should also be able to use a List<string> for notes, if you would prefer that.

how can convert var to List c#

I would like to convert var to list value . I am getting 'myobj' var value. Now how can i convert to CandidateResume list ?.
JavaScriptSerializer jsSerializer = new JavaScriptSerializer() { MaxJsonLength = 86753090 };
var myobj = jsSerializer.Deserialize<List<List<CandidateResume>>>(description);
My CandidateResume class like this
public class CandidateResume
{
public string name { get; set; }
public string url { get; set; }
public string summary { get; set; }
public string role { get; set; }
public string compensation { get; set; }
public string education { get; set; }
public string expertise { get; set; }
public string years { get; set; }
public string relocation { get; set; }
public string resume { get; set; }
public string resumeExtension { get; set; }
public string resumeMimeType { get; set; }
}
Please see this current item value in screenshot
How can i catch item value ?
foreach (var item in myobj)
{
WebScrappingCandidate webScrappingCandidate = new WebScrappingCandidate();
}
Deserialize<T> returns a T (MSDN), which means myObj is already of type: List<List<CandidateResume>>.
Remember, var is not a type, it just uses type inference to be shorthand for: "Be whatever type I'm being assigned to".
To "flatten" this list, you could just use SelectMany:
foreach (CandidateResume resume in myObj.SelectMany(i => i))
{
}
Of course, there are other methods as well, but the crux of the answer is that you already have a list of candidate resumes. No conversion required.
You already have a list, the Deserialize method returns a typed result:
List<List<CandidateResume>> myobj =
jsSerializer.Deserialize<List<List<CandidateResume>>>(description);
When you loop through that, each item is a list:
foreach (List<CandidateResume> item in myobj) {
...
}

Deserialize JSON with dynamic objects

I have a JSON object that comes with a long list of area codes. Unfortunately each area code is the object name on a list in the Data object. How do I create a class that will allow RestSharp to deserialize the content?
Here's how my class looks now:
public class phaxioResponse
{
public string success { get; set; }
public string message { get; set; }
public List<areaCode> data { get; set; }
public class areaCode
{
public string city { get; set; }
public string state { get; set; }
}
}
And here's the JSON content:
{
success: true
message: "277 area codes available."
data: {
201: {
city: "Bayonne, Jersey City, Union City"
state: "New Jersey"
}
202: {
city: "Washington"
state: "District Of Columbia"
} [...]
}
Since this JSON is not C# friendly, I had to do a little bit of hackery to make it come out properly. However, the result is quite nice.
var json = JsonConvert.DeserializeObject<dynamic>(sampleJson);
var data = ((JObject)json.data).Children();
var stuff = data.Select(x => new { AreaCode = x.Path.Split('.')[1], City = x.First()["city"], State = x.Last()["state"] });
This code will generate an anonymous type that best represents the data. However, the anonymous type could be easily replaced by a ctor for a more normal DTO class.
The output looks something like this:
your json is incorrect, but if you do correct it you can use a json-to-csharp tool like the one on http://json2csharp.com/ to generate your classes:
public class __invalid_type__201
{
public string city { get; set; }
public string state { get; set; }
}
public class Data
{
public __invalid_type__201 __invalid_name__201 { get; set; }
}
public class RootObject
{
public bool success { get; set; }
public string message { get; set; }
public Data data { get; set; }
}
I don't know anything about RestSharp, but if you're using Newtonsoft on the server side, then you can just pass a JObject to your method. Then you can interrogate the object to see what type of object it really is and use JObject.ToObject() to convert it.
I think using Dictionary<int,areaCode> is the easiest way.
public class phaxioResponse
{
public string success { get; set; }
public string message { get; set; }
public Dictionary<int,areaCode> data { get; set; }
public class areaCode
{
public string city { get; set; }
public string state { get; set; }
}
}
Then:
var res= JsonConvert.DeserializeObject<phaxioResponse>(json);
Console.WriteLine(string.Join(",", res.data));

Categories