Advice needed to parse this JSON in .NET - c#

Given the following JSON samples, what is the best way to parse this in c# .NET?
{"data":{"5":{"isDeleted":"false","day":"THU"}},"action":"edit"}
{"data":{"7":{"isDeleted":"false","name":"alex"}},"action":"edit"}
{"data":{"90":{"isDeleted":"true","job":"software"}},"action":"edit"}
I have looked into JSON serializing into an object but because the data could be different each time i can't map it directly to a model.

So the model for this could be
public class Record
{
public Dictionary<string, Dictionary<string, string>> Data { get; set; }
public string Action { get; set; }
}

You can deserialize the JSON into a dynamic object, which allows you to access the properties of the JSON object without having to define a specific model with JsonSerializer of System.Text.Json:
string jsonString = "{\"data\":{\"5\":{\"isDeleted\":\"false\",\"day\":\"THU\"}},\"action\":\"edit\"}";
dynamic jObject = JsonSerializer.Deserialize<dynamic>(jsonString);
string action = jObject .action;
dynamic data = jObject .data;
string isDeleted = data["5"].isDeleted;
string day = data["5"].day;

Related

Cannot identify data structure from JSON to deserialize into object

Having issue with deserializing json string into object.
The main issue is that I can not identify what type of object this string represents:
string jsonDataText = #"{""sun"":""heat"", ""planet"":""rock"", ""earth"":""water"", ""galaxy"":""spiral""}";
It looks like List of KeyValuePair objects, but when I try to deserialize by using Newtonsoft.Json:
var clone = JsonConvert.DeserializeObject<List<KeyValuePair<string,string>>>(jsonDataText);
I have got an exception:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[System.Collections.Generic.KeyValuePair`2[System.String,System.String]]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
Had also tried with Maps and string(multidimensional) arrays but got the same exception...
It looks like Dictionary< string,string > to me.
JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonDataText);
With using JObject its easy to read any key/value pair from JSON.
So you no more need to identify what the type of your key/value pair in your json.
string jsonDataText = #"{""sun"":""heat"", ""planet"":""rock"", ""earth"":""water"", ""galaxy"":""spiral""}";
//Parse your json to dictionary
Dictionary<string, string> dict = JObject.Parse(jsonDataText).ToObject<Dictionary<string, string>>();
You need to add this namespace to your program => using Newtonsoft.Json.Linq;
Output:
It looks like to me as a simple class.
public class MyClass
{
[JsonProperty("sun")]
public string Sun { get; set; }
[JsonProperty("planet")]
public string Planet { get; set; }
[JsonProperty("earth")]
public string Earth { get; set; }
[JsonProperty("galaxy")]
public string Galaxy { get; set; }
}
Deserialize:
var clone = JsonConvert.DeserializeObject<MyClass>(jsonDataText);

Deserializing JSON into string array OR datatable in C#

string json = {"house":"#21-3-157/18, Sri Vaibhav","loc":"Subash nagar,Bolar","country":"India"}
getting error while deserialize mentioned json string in array
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type 'System.Collections.Generic.List because the type requires a
JSON array (e.g. [1,2,3]) to deserialize correctly.
I've tried many different ways of doing this, each time failed. please help.
Use Json.NET.
Example from https://www.newtonsoft.com/json/help/html/QueryJsonDynamic.htm
string json = #"[
{
'Title': 'Json.NET is awesome!',
'Author': {
'Name': 'James Newton-King',
'Twitter': '#JamesNK',
'Picture': '/jamesnk.png'
},
'Date': '2013-01-23T19:30:00',
'BodyHtml': '<h3>Title!</h3>\r\n<p>Content!</p>'
}
]";
dynamic blogPosts = JArray.Parse(json);
dynamic blogPost = blogPosts[0];
string title = blogPost.Title;
Console.WriteLine(title);
// Json.NET is awesome!
string author = blogPost.Author.Name;
Console.WriteLine(author);
// James Newton-King
DateTime postDate = blogPost.Date;
Console.WriteLine(postDate);
// 23/01/2013 7:30:00 p.m.
Another example without dynamic https://www.newtonsoft.com/json/help/html/QueryJson.htm
You can use NewtonsoftJson library to parse json data easily without creating concrete class
using Newtonsoft.Json;
dynamic parse = Newtonsoft.Json.JsonConvert.DeserializeObject(json );
string house = parse.house.Value;
etc..
Your JSON string is not in a format to convert to JSON string array. If you want to Deserialize JSON string to List then your format should be like below,
string json = "[\"house\",\"loc\"]";
In you want your string to Desrialize to array then you need corresponding entity like below,
public class Address
{
public string House { get; set; }
public string Loc { get; set; }
public string Country { get; set; }
}
Then you should deserialize to that type,
string json = "[{\"house\":\"#21-3-157/18,Sri Vaibhav\",\"loc\":\"Subash nagar,Bolar\",\"country\":\"India\"}]";
List<Address> array = JsonConvert.DeserializeObject<List<Address>>(json);

Deserialize JSON response using Newtonsoft.Json

I have a web service which return response in JSON format as below.
{"123":{"Name":"Abcd", "Age":"30"},"231":{"Name":"xyz", "Age":"20"}, "543":{"Name":"pqr", "Age":"35"}}
I want to deserialize this response in C# and wants to display it.
How can I do with Newtonsoft.Json library.
Please help me.
I'm going to assume that "123", "231", and "543" are identifiers and not constant property names. In that case what you have is a dictionary of objects. First, define a class that maps to the object.
public class Something
{
public string Name { get; set; }
public string Age { get; set; }
}
Then deserialize into a dictionary of those objects.
var whatever = JsonConvert.DeserializeObject<Dictionary<string, Something>>(json);

Separating array and element from a JSON string

I am connecting you Google Places API to retrive results in the form of a JSON string. You can view the complete format of the string Here.
If you a look at it you will see that the actual results array starts after two elements which are html_attributions and next_page_token.
So When i try to deserialize it in this way:
var serializer = new JavaScriptSerializer();
var arr= serializer.Deserialize(result,typeof(string[]));
I get an empty array.
My question is how is there a way i can separate html_attributions and next_page_token fields and the pass the valid results array from the string to be deserialized?
I don't understand the part where you wish to seperate the html_attributions and the next_page_token.
Wouldn't it be sufficient to just deserialize the response with whatever properties that you need?
For example, you can deserialize the response to only retrieve the values that you desire;
// I represent the wrapper result
class Result
{
public List<string> html_attributions { get; set; }
public string next_page_token { get; set; }
public List<ResultItem> results { get; set; }
}
// I represent a result item
class ResultItem
{
public string id { get; set; }
public string name { get; set; }
}
// the actual deserialization
Result Deserialize(string json)
{
var serializer = new JavaScriptSerializer();
return serializer.Deserialize(json, typeof(Result));
}
Edit:
The reason that your deserialization doesn't return you a array of strings is because the response that you retrieve is infact an object and not an array, however the parameter within that object which is named results is an array. In order for you to deserialize more properties you'll have to define them in your "ResultItem" class, sorry for my poor naming here.
For instance, if you'd wish to also retrieve the icon property per result you'll have to add a property named "icon" of type string.
Meanwhile the property "photos" is an array, in order to deserialize it you'll have to create another class and add a property of type list/array of that newly created class, and it has to be named "photos" unless you use a different serializer or use DataContract and DataMember attributes (using the Name property for field mapping).
// the representation of a photo within a result item
class Photo
{
public int height { get; set; }
public List<string> html_attributions { get; set; }
public string photo_reference { get; set; }
public int width { get; set; }
}
// I represent a result item
class ResultItem
{
public string id { get; set; }
public string name { get; set; }
// the added icon
public string icon { get; set; }
// the added photos collection, could also be an array
public List<Photo> photos { get; set; }
}
Just look at the JSON result to figure out what other properties that you might want to add, for instance the "scope" property is an string whilst the "price_level" is an integer.
If I understand your comment correctly you're only interested in the actual results, you'll still have to deserialize the response correctly with its wrapper.
// the actual deserialization
List<ResultItem> Deserialize(string json)
{
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize(json, typeof(Result));
return result.results;
}
Edit2:
If you really want a string[] as a result you could simply take use of System.Linq using the code above.
string[] stringArray = result.results.Select(r => string.Format("id:{0} - name:{1}", r.id, r.name)).ToArray();
Edit3:
Instead of using the JavascriptSerializer you could use JObject functionality which can be found in the Newtonsoft.Json.Linq library.
var jsonObject = JObject.Parse(json);
string[] results = jsonObject.SelectTokens("results").Select(r => r.ToString()).ToArray();
This will give you an array of strings where each value within the array is the actual json string for each result.
If you however would like to query for the coordinates only:
var jsonObject = JObject.Parse(json);
var coordinates = jsonObject["results"]
.Select(x => x.SelectToken("geometry").SelectToken("location"))
.Select(x => string.Format("{0},{1}", (string)x.SelectToken("lat"), (string)x.SelectToken("lng")))
.ToArray();
This would give you an array of coordinates, eg:
[
"-33.867217,151.195939",
"-33.866786,151.195633",
...
]
Whatever approach you choose you'll be able to accomplish same results using either Newtonsoft or the .net serializer, whilst the Newtonsoft approach would allow you to query without creating strong types for deserialization.
I don't find the point of "[...] pass the valid results array from the string to be deserialized".
Maybe you need to switch to JSON.NET and do something like this:
// You simply deserialize the entire response to an ExpandoObject
// so you don't need a concrete type to deserialize the whole response...
dynamic responseEntity = JsonConvert.DeserializeObject<ExpandoObject>(
googlePlacesJson, new ExpandoObjectConverter()
);
// Now you can access result array as an `IEnumerable<dynamic>`...
IEnumerable<dynamic> results = responseEntity.results;
foreach(dynamic result in results)
{
// Do stuff for each result in the whole response...
}

Parsing JSON data with javascriptserializer throws exception

I am getting JSON data in following format:
"[[\"NAME\",\"state\"],\n[\"Alabama\",\"01\"],\n[\"Alaska\",\"02\"]]"
I am trying to parse it with System.Web.Script.Serialization.JavaScriptSerializer the following way:
[Serializable]
private class State
{
private string Name { get; set; }
private string Code { get; set; }
}
private static List<State> getStates(string jsonData)
{
var json = new JavaScriptSerializer();
var parsedResult = json.Deserialize<List<State>>(jsonData);
return parsedResult;
}
The error I am getting is Type 'State' is not supported for deserialization of an array.
What am I doing wrong?Please suggest a way out.
Update
I have somewhat solved the problem since I need only a collection of the data in a queryable format. The following code did the trick:
var parsedResult = json.Deserialize<List<string[]>>(jsonData);
You have found workaround, nevertheless I think it's good to have explanation for the issue.
The problem you have is in brackets; [] means array, whereas object is market with {}. This means that to deserialize input string in array of State objects your input string should be formatted in following way:
[{\"NAME\",\"state\"},\n{\"Alabama\",\"01\"},\n{\"Alaska\",\"02\"}]

Categories

Resources