Parsing JSON data with javascriptserializer throws exception - c#

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\"}]

Related

Unable to deserialize Json string array of arrays into object when using Newtonsoft.Json

i am using Newtonsoft.Json and trying to deserialize an array of arrays Json string into C# object i created.
This is the json string -
[4615,4618,4619,4626,4615,4626,4631,4636,4637],[4615,4618,4619,4626,4615,4626,4631,4636,4637],[4615,4618,4619,4626,4615,4626,4631,4636,4637]
This is my object model -
public class NumberMatrix
{
public List<int> NumberIDs { get; set; }
public NumberMatrix()
{
this.NumberIDs = new List<int>();
}
}
This is how i try to convert -
var numbers = HttpContext.Current.Request.Params["Numbers"];
var numberIDsMatrix = JsonConvert.DeserializeObject<List<NumberMatrix>>(numbers);
i tried to deserialize the json in few ways, and got different errors. is it possible to deserialize this json string? how?
That isn't valid JSON, you need to surround it with [...] for example. You could do this:
var result = JsonConvert.DeserializeObject<List<List<int>>>($"[{numbers}]");

How to parse json string in c#

How can i parse a json string in c# controller
public ActionResult GetAjaxSession(string search)
{
...
}
Variable which containt the json string :
search
The Json string :
[{"id_employe":"35"},{"id_employe":"80"},{"id_employe":"136"},{"id_employe":"140"}]
I want to get all id_employe from the string
But parsing would be the right way, to get the right data out of your string.
Example with using Newtonsoft.Json:
var objects = JsonConvert.DeserializeObject<List<MyObj>>(jsonText);
With the class:
public class MyObj
{
public string id_employe { get; set; }
}
Malior's approach is perfectly fine, it's a typed approach. I'd like to mention an alternative way, using Linq and dynamic:
var jsonText="[{\"id_employe\":\"35\"},{\"id_employe\":\"80\"},"
+"{\"id_employe\":\"136\"},{\"id_employe\":\"140\"}]";
var objects = JsonConvert.DeserializeObject<List<dynamic>>(jsonText);
var values = objects.Select(s=>s.id_employe).ToList();
Fiddle
This will create a list, so values contains the following elements:
35,80,136,140
Because it is dynamic, you don't need to declare an extra class. Note that both approaches will throw a JsonReaderException if there is anything wrong with the JSON string (e.g. missing [ etc.). And if the property name isn't found it can throw a RuntimeBinderException - so you should use a try ... catch block.

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...
}

Manipulate Values of Stringfied values on C#

I have a below code that used JSON.stringify to the object then passed it on POST method (Please see below Javascript code). I'm getting those values on the backend using C#. My problem is, how could I convert/manipulate/access the stringified values. Please see below C# code
Javascript:
var json_db = JSON.stringify(selectedDbInfo);
$.post("../FormActions/DatabaseChanges.aspx", { action: "savedb", orderNumber: orderNumber, selectedDb: json_db},
function (response) {
alert('ok');
});
C#:
var dbValue = c.Request.Params["selectedDb"];
below is the result value of dbValue
"[{\"dbname\":\"BASINS\",\"distance\":\"0\"},{\"dbname\":\"BROWNFIELD\",\"distance\":\"0.5\"},{\"dbname\":\"BRS\",\"distance\":\"0\"}]"
You need to parse the JSON into a .NET array or List.
Many use json.NET for this: http://james.newtonking.com/json
At a push you could use some string manipulation to populate your objects one by one, but I wouldn't recommend that.
There are many samples here on SO.
if you're just want to convert it dictionary look here:
How can I deserialize JSON to a simple Dictionary<string,string> in ASP.NET?
However, there's a built in mechanism in ASP.NET MVC that serializes automatically your json param to predefined objects at your convenient.
You may define a class having the fields like dbname and distance as properties. Then you may deserialize the json string dbValue into a list of that type using NewtonSoft.Json. Please see the code below:
var list = JsonConvert.DeserializeObject<List<RootObject>>(dbValue);
foreach (var item in list)
{
Console.WriteLine(string.Format("dbname: {0}, distance: {1}", item.dbname, item.distance));
}
Ans the definition of RootObject is as simple as you guess:
public class RootObject
{
public string dbname { get; set; }
public string distance { get; set; }
}
Create a custom serializable data contract class, say DatabaseDistance, with following properties:
[DataMember(Name = "dbname")]
private string name;
[DataMember(Name = "distance")]
private double distance;
and use following method for deserialization:
public static T FromJSON<T>(string jsonValue, IEnumerable<Type> knownTypes)
{
//validate input parameters here
T result = default(T);
try
{
using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(jsonValue)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T), knownTypes);
result = (T)serializer.ReadObject(stream);
}
}
catch (Exception exception)
{
throw new Exception("An error occurred while deserializing", exception);
}
return result;
}
pass list of your objects as type parameter

C# How to know which element is root object for deserialization?

I used json2csharp to get this:
http://pastebin.com/pbDYCrWk
From that, I wish to get the title that is held in the Oembed section.
I'm using this code:
string url = "http://www.reddit.com/r/all.json";
string jsonText = await DoStuff(url);
var json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonText);
var deserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Page.Oembed>(json);
string test = deserializeObject.title;
And I assumed it would work, however on the line with the deserializeObject variable, I get an error saying it can't do it.
I tried using Page.RootObject however it doesn't work either, and I assumed it would since it seems to be the root.
What am I doing wrong and how can I solve it? Thanks.
If you used Json2CSharp then it is RootObject:
public class RootObject
{
public string kind { get; set; }
public Data data { get; set; }
}
Should be:
var deserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<JuicyReddit.RootObject>(json);

Categories

Resources