C# deserialize JSON using JavaScriptSerializer.DeserializeObject - c#

I am not a C# programmer, but rather playing with the language from time to time. I wonder, if I have a JSON string which I want to deserialize using JavaScriptSerializer.DeserializeObject, how could I do that. For instance, if I have a JSON:
{
"Name": "col_name2",
"Value": [
{
"From": 100,
"To": 200
},
{
"From": 100,
"To": 200
}
]
}
And I have that JSON string in a variable called sJson:
using System.Web.Script.Serialization;
...
JavaScriptSerializer jss = new JavaScriptSerializer();
Object json = jss.DeserializeObject(sJson);
and now how do I use this Object json variable?
Note: I already know how to do it using System.Web.Script.Serialization.Deserialize<T> method.

Look at this post for Davids Answer:
Deserialize json object into dynamic object using Json.net
You can put it into a dynamic (underlying type is JObject)
Then you can than access the information like this:
JavaScriptSerializer jss = new JavaScriptSerializer();
dynamic json = jss.DeserializeObject(sJson);
Console.WriteLine(json["Name"]); // use as Dictionary
I would prefer create a data transfer object (DTO) represent your JSON Structure as a c# class.

You could declare new custom classes for this specific case:
public class CustomClass
{
public string Name { get; set; }
public List<ValueClass> Value { get; set; }
}
public class ValueClass
{
public int From { get; set; }
public int To { get; set; }
}
Then deserialize directly to those classes (the deserializer will automatically map the correct properties):
JavaScriptSerializer jss = new JavaScriptSerializer();
CustomClass json = (CustomClass)jss.Deserialize(sJson, typeof(CustomClass));
Moreover if you have more than 1 items, this is easy as well:
List<CustomClass> json = (List<CustomClass>)jss.Deserialize(sJson, typeof(List<CustomClass>));

Related

SerializationException: The data contract type <TypeName> could not be deserialized because more than one data item <FieldName> was found in the input

Im getting an 'SerializationException' exception when deserializing data's from json file:
public static T Deserialize(string FilePath)
{
using (FileStream FS = new FileStream(FilePath, FileMode.OpenOrCreate))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(FS) ?? null;
}
}
and this is how im trying to deserialize:
ServiceEntity resultEntity = JsonHelper<ServiceEntity>.Deserialize(DestinationFilePath);
while (resultEntity != null)
{
ListViewItem listViewItem = new ListViewItem(new string[] { resultEntity.ServiceName, resultEntity.ServiceStatus.ToString(), resultEntity.DisplayName });
lvServices.Items.Add(listViewItem);
}
T is this:
[DataContract]
sealed class ServiceEntity
{
[DataMember]
public string DisplayName { get; set; }
[DataMember]
public string ServiceName { get; set; }
[DataMember]
public ServiceControllerStatus ServiceStatus { get; set; }
}
JSON data is : https://pastebin.com/M18GD8yh
Your data is a single line of hundreds of JSON objects. The code reads the entire file and tries to deserialize it into a single C# object. You need to come up with a way to process each object separately. If you have control over the input file, it might be a good start to put the objects into an array, and deserialize that.
[{
"DisplayName": "AarSvc_2dae3",
"ServiceName": "AarSvc_2dae3",
"ServiceStatus": 1
},{
"DisplayName": "AMD External Events Utility",
"ServiceName": "AMD External Events Utility",
"ServiceStatus": 4
}, {
…
}]
what you call a json, is not a valid json string, it is just a collection of json-like peaces in one string. But you can easily fix it
string json = File.ReadAllText(filePath;
json="["+json.Replace("}{","},{")+"]";
after this you can parse it as Json Array
JArray services = JArray.Parse(json);
or you can deserialize it in your c# class
using Newtonsoft.Json;
List<ServiceEntity> services = JsonConvert.DeserializeObject<List<ServiceEntity>>(json);
or try your fancy serializer.
Output in a json format
[
{
"DisplayName": "AarSvc_2dae3",
"ServiceName": "AarSvc_2dae3",
"ServiceStatus": 1
},
{
"DisplayName": "AMD External Events Utility",
"ServiceName": "AMD External Events Utility",
"ServiceStatus": 4
},
....
]
UPDATE
If you have an acces to code to create a json from the c# object it is better to fix it there. IMHO you can use Newtonsonft.Json as a serializer . You can install it using a Nuget package. After this use this code
using Newtonsoft.Json;
List<ServiceEntity> services = ... your code to create list of services;
var json = JsonConvert.SerializeObject(services);
if you need to save this json in a file
File.WriteAllText(FilePath, json);

Json arry and other properties deserialization (C#)

I have the following json that contains an unnamed array and other named properties. I'd like to know how to deserialize it to a class, using Newtonsoft.Json.
{
"message": "success",
[
{
"timestamp": 1509723862,
"tid": 84823616,
"price": "7344.7",
"amount": "0.36108123",
"exchange": "bitfinex",
"type": "sell"
},
{
...
}
]
}
I know I could deserialize the array using
serializer.DeserializeObject< List < Response > >(serializedObject), but as the json contains other properties, it is not a json-array string.
Is there any configuration that I could use to tell Newtonsoft.Json to deserialize the array into a List, and the 'message' property to a string, in the class bellow:
public class Response
{
public string Message {get;set;}
public List<ResponseItem> ResponseItems {get;set;}
}
public class ResponseItem {
string timestamp {get;set;}
(...)
}
A JSON can't have both an unnamed array and a named value on the same level. The JSON is invalid. Either everything is keyed, or it's an unkeyed array. Can't have both.
I think it's not a good idea to concate the two Json's.
Use your own Deserializer and pass your two Json's:
public static class ResponseDeserializer
{
public static Response Deserialize(string psMessage, string psResponeItems)
{
dynamic loMessage = JsonConvert.DeserializeObject(psMessage);
return new Response()
{
Message = loMessage.message,
ResponseItems = JsonConvert.DeserializeObject<List<ResponseItem>>(psResponeItems)
};
}
}
And use it:
string lsMessage = "{\"message\":\"Unknown symbol\"}";
string lsResponseItems = "[{\"timestamp\":1509726632,\"tid\":84840931,\"price\":\"7298.8\",\"amount\":\"0.0044733\",\"exchange\":\"bitfinex\",\"type\":\"sell\"},{\"timestamp\":1509726630,\"tid\":84840921,\"price\":\"7297.3\",\"amount\":\"0.11550649\",\"exchange\":\"bitfinex\",\"type\":\"sell\"},{\"timestamp\":1509726630,\"tid\":84840911,\"price\":\"7297.2\",\"amount\":\"0.0214149\",\"exchange\":\"bitfinex\",\"type\":\"buy\"},{\"timestamp\":1509726629,\"tid\":84840909,\"price\":\"7297.2\",\"amount\":\"0.41004892\",\"exchange\":\"bitfinex\",\"type\":\"buy\"}]";
var loResponse = ResponseDeserializer.Deserialize(lsMessage, lsResponseItems);
Console.WriteLine(loResponse.Message);

Best approach in C# to deserialize json object that can be array or single object [duplicate]

This question already has answers here:
How to handle both a single item and an array for the same property using JSON.net
(9 answers)
Closed 4 years ago.
We're dealing with an json API result. Just to make our lives difficult the provider of the API returns on of the items as an array if there are multiple objects, or as a single object if there is only one.
e.g.
If there is only one object...
{
propertyA: {
first: "A",
second: "B"
}
}
Or if there are multiple:
{
propertyA: [
{
first: "A",
second: "B"
},
{
first: "A",
second: "B"
}
]
}
Does anybody have a good way of dealing with this scenario?
Ideally we'd like to serialize both to
public class ApiResult{
public ApiItem[] PropertyA {get;set;}
}
This works for the second example but of you encounter the first example you get a A first chance exception of type 'System.MissingMethodException' occurred in System.Web.Extensions.dll
Additional information: No parameterless constructor defined for type of 'ApiItem[]'.
I assume the class definition is as below
public class ApiResult
{
public ApiItem[] PropertyA { get; set; }
}
public class ApiItem
{
public string First { get; set; }
public string Second { get; set; }
}
You can deserialize the json into a dynamic variable, then check the type of d.propertyA. If it's JArray then propertyA is an array, so you can deserialize the json into a ApiResult. If it's JObject then propertyA is a single object, so you need to manually construct ApiItem and assign it to PropertyA of ApiResult. Consider the method below
public ApiResult Deserialize(string json)
{
ApiResult result = new ApiResult();
dynamic d = JsonConvert.DeserializeObject(json);
if (d.propertyA.GetType() == typeof (Newtonsoft.Json.Linq.JObject))
{
// propertyA is a single object, construct ApiItem manually
ApiItem item = new ApiItem();
item.First = d.propertyA.first;
item.Second = d.propertyA.second;
// assign item to result.PropertyA[0]
result.PropertyA = new ApiItem[1];
result.PropertyA[0] = item;
}
else if (d.propertyA.GetType() == typeof (Newtonsoft.Json.Linq.JArray))
{
// propertyA is an array, deserialize json into ApiResult
result = JsonConvert.DeserializeObject<ApiResult>(json);
}
return result;
}
The code above will return an instance of ApiResult for both json examples.
Working demo: https://dotnetfiddle.net/wBQKrp
Building upon ekad's answer, I made the code:
Shorter: as now you don't have map one by one every property inside ApiItem
Probably faster in the case of being already an Array (by not calling to both versions of JsonConvert.DeserializeObject with the same input of the json string)
Explicit about how to introduce other properties
Handling the error case of unknown type of our propertyA (the one that can be either an array or an object).
Notice that instead of JsonConvert.DeserializeObject, I call JObject.Parse, and then ToObject<> for only the part I need in that particular case:
static ApiResult Deserialize(string json)
{
JObject j = JObject.Parse(json);
var propA = j["propertyA"];
switch (propA.Type.ToString())
{
case "Object":
return new ApiResult {
PropertyA = new[]{propA.ToObject<ApiItem>()},
SomethingElse = j["somethingElse"].ToObject<string>(),
};
case "Array":
return j.ToObject<ApiResult>();
default:
throw new Exception("Invalid json with propertyA of type " + propA.Type.ToString());
}
}
The API is pretty much the same, but I've added SomethingElse (for showing how other properties can be easily handled with this approach):
public class ApiResult
{
public ApiItem[] PropertyA { get; set; }
public string SomethingElse { get; set; }
}
public class ApiItem
{
public string First { get; set; }
public string Second { get; set; }
}
Working demo: https://dotnetfiddle.net/VLbTMu
JSON# has a very lightweight tool that allows you to achieve this. It will retrieve embedded JSON, regardless of whether or not the embedded JSON is an object, or array, from within larger JSON objects:
const string schoolMetadata = #"{ "school": {...";
var jsonParser = new JsonObjectParser();
using (var stream =
new MemoryStream(Encoding.UTF8.GetBytes(schoolMetadata))) {
Json.Parse(_jsonParser, stream, "teachers");
}
Here we retrieve a "teachers" object from within a larger "school" object.
best way to Serialize/Deserialize to/from JSON is Json.NET
Popular high-performance JSON framework for .NET
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Sizes = new string[] { "Small" };
string json = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "Expiry": "2008-12-28T00:00:00",
// "Sizes": [
// "Small"
// ]
//}
string json = #"{
'Name': 'Bad Boys',
'ReleaseDate': '1995-4-7T00:00:00',
'Genres': [
'Action',
'Comedy'
]
}";
Movie m = JsonConvert.DeserializeObject<Movie>(json);
string name = m.Name;
// Bad Boys

How to deserialize JSON array of objects to c# structure

I have a json string that was created from serializing an array of objects :
[
{
"html": "foo"
},
{
"html": "bar"
}
]
How can I deserialize it to some iterable C# structure ? I've tried this code, but I'm getting No parameterless constructor defined for type of 'System.String'. error :
string[] htmlArr = new JavaScriptSerializer().Deserialize<String[]>(html);
What I want to receive is an iterable structure to get each 'html' object.
Use a class for each JSON object. Example:
public class HtmlItem
{
[DataMember(Name = "html")]
public string Html { get; set; }
}
JavaScriptSerializer ser = new JavaScriptSerializer();
// Serialize
string html = ser.Serialize(new List<HtmlItem> {
new HtmlItem { Html = "foo" },
new HtmlItem { Html = "bar" }
});
// Deserialize and print the html items.
List<HtmlItem> htmlList = ser.Deserialize<List<HtmlItem>>(html);
htmlList.ForEach((item) => Console.WriteLine(item.Html)); // foo bar
You can use Newtonsoft Json.NET (available from NuGet)
string json = #"[{""html"": ""foo""},{""html"": ""bar""}]";
var items = JsonConvert.DeserializeObject<List<Item>>(json);
Where
public class Item
{
public string Html { get; set; }
}
The docs site apparently isn't working right now... But I would try using JSON.NET ( http://james.newtonking.com/projects/json/help/ )
There are a couple of ways you can do it. You can deserialize in a very dynamic not type strict way or you can define an object that matches the json object exactly and deserialize into that. If there are many formats of JSON you'll have to serialize I would recommend using schemas.
Answer of nekman is not completely correct, the attribute should be JsonPropery instead of DataMember. (in this case you can remove the attribute since the deserializer doesn't care about the capital H)
public class HtmlItem
{
[JsonProperty("html")]
public string Html { get; set; }
}
JavaScriptSerializer ser = new JavaScriptSerializer();
// Serialize
string html = ser.Serialize(new List<HtmlItem> {
new HtmlItem { Html = "foo" },
new HtmlItem { Html = "bar" }
});
// Deserialize and print the html items.
List<HtmlItem> htmlList = ser.Deserialize<List<HtmlItem>>(html);
htmlList.ForEach((item) => Console.WriteLine(item.Html)); // foo bar

Deserializing JSON using C#

Finding some difficulty in sourcing information in trying to deserialize JSON in C#.
I have results from Google custom search returned in JSON format. I just want to check through my steps and establish the order in trying to deserialize it. Is this right?
I need to create classes to match
the JSON format. Kind of like a
creating schema file.
Use the JavaScriptSerializer() class and
deserialize method to extract the
relevant bits.
One of the issues I think I am going to run into is that I don't require all of the data returned but only the html links. How can I achieve that?
UPDATE
I have updated my question with the following JSON snippet and C# code. I want to output the string 'links' to console but it doesn't seem to be working. I think I am defining my classes wrongly?
JSON from Google Custom Search
handleResponse({
"kind": "customsearch#search",
"url": {
"type": "application/json",
"template": "https://www.googleapis.com/customsearch/v1?q\u003d{searchTerms}&num\u003d{count?}&start\u003d{startIndex?}&hr\u003d{language?}&safe\u003d{safe?}&cx\u003d{cx?}&cref\u003d{cref?}&sort\u003d{sort?}&alt\u003djson"
},
"queries": {
"nextPage": [
{
"title": "Google Custom Search - lectures",
"totalResults": 9590000,
"searchTerms": "lectures",
"count": 1,
"startIndex": 2,
"inputEncoding": "utf8",
"outputEncoding": "utf8",
"cx": "017576662512468239146:omuauf_lfve"
}
],
"request": [
{
"title": "Google Custom Search - lectures",
"totalResults": 9590000,
"searchTerms": "lectures",
"count": 1,
"startIndex": 1,
"inputEncoding": "utf8",
"outputEncoding": "utf8",
"cx": "017576662512468239146:omuauf_lfve"
}
]
},
"context": {
"title": "Curriculum",
"facets": [
[
{
"label": "lectures",
"anchor": "Lectures"
}
],
[
{
"label": "assignments",
"anchor": "Assignments"
}
],
[
{
"label": "reference",
"anchor": "Reference"
}
]
]
},
"items": [
{
"kind": "customsearch#result",
"title": "EE364a: Lecture Videos",
"htmlTitle": "EE364a: \u003cb\u003eLecture\u003c/b\u003e Videos",
"link": "http://www.stanford.edu/class/ee364a/videos.html",
"displayLink": "www.stanford.edu",
"snippet": "Apr 7, 2010 ... Course materials. Lecture slides · Lecture videos (2008) · Review sessions. Assignments. Homework · Reading. Exams. Final exam ...",
"htmlSnippet": "Apr 7, 2010 \u003cb\u003e...\u003c/b\u003e Course materials. \u003cb\u003eLecture\u003c/b\u003e slides · \u003cb\u003eLecture\u003c/b\u003e videos (2008) · Review sessions. \u003cbr\u003e Assignments. Homework · Reading. Exams. Final exam \u003cb\u003e...\u003c/b\u003e",
"cacheid": "TxVqFzFZLOsJ"
}
]
}
);
C# Snippet
public class GoogleSearchResults
{
public string link { get; set; }
}
public class Program
{
static void Main(string[] args)
{
//input search term
Console.WriteLine("What is your search query?:");
string searchTerm = Console.ReadLine();
//concantenate the strings using + symbol to make it URL friendly for google
string searchTermFormat = searchTerm.Replace(" ", "+");
//create a new instance of Webclient and use DownloadString method from the Webclient class to extract download html
WebClient client = new WebClient();
string Json = client.DownloadString("https://www.googleapis.com/customsearch/v1?key=My Key&cx=My CX&q=" + searchTermFormat);
//create a new instance of JavaScriptSerializer and deserialise the desired content
JavaScriptSerializer js = new JavaScriptSerializer();
GoogleSearchResults results = js.Deserialize<GoogleSearchResults>(Json);
Console.WriteLine(results);
//Console.WriteLine(htmlDoc);
Console.ReadLine();
}
}
Thanks
I use your #2 approach: deserialize with the JavaScriptSerializer.
This is what I do to deserialize a response from Facebook:
// get the id for the uploaded photo
var jss = new JavaScriptSerializer();
var resource = jss.Deserialize<Facebook.Data.Resource>(responseText);
....where Facebook.Data.Resource is defined like this:
namespace Facebook.Data
{
public class Resource
{
public string id { get; set; }
}
}
The responseText that I am deserializing from looks like this:
{"id":"10150111918987952",
"from":{"name":"Someone",
"id":"782272221"},
"name":"uploaded from Cropper. (at 12\/15\/2010 7:06:41 AM)",
"picture":"http:\/\/photos-f.ak.fbcdn.net\/hphotos-ak-snc4\/hs817.snc4\/69790_101501113333332_782377951_7551951_8193638_s.jpg",
...
But since I have only one property defined in the Resource class, I only deserialize that. Define the fields in your class that you want to deserialize.
It works to use inheritance, of course. You can define your data classes like this:
namespace Facebook.Data
{
public class Resource
{
public string id { get; set; }
}
public class Person : Resource
{
public string name { get; set; }
}
}
...and then you can deserialize a Person object.
EDIT
Ok, given the sample json you provided in the updated question, here's how I wrote the classes to hold the response:
public class GoogleSearchItem
{
public string kind { get; set; }
public string title { get; set; }
public string link { get; set; }
public string displayLink { get; set; }
// and so on... add more properties here if you want
// to deserialize them
}
public class SourceUrl
{
public string type { get; set; }
public string template { get; set; }
}
public class GoogleSearchResults
{
public string kind { get; set; }
public SourceUrl url { get; set; }
public GoogleSearchItem[] items { get; set; }
// and so on... add more properties here if you want to
// deserialize them
}
And here's the C# code to deserialize:
// create a new instance of JavaScriptSerializer
JavaScriptSerializer s1 = new JavaScriptSerializer();
// deserialise the received response
GoogleSearchResults results = s1.Deserialize<GoogleSearchResults>(json);
Console.WriteLine(s1.Serialize(results));
Some comments:
The toplevel class to hold the search result is called GoogleSearchResults.
The first property in the GoogleSearchResults class is kind, corresponding to the first named property in the json object. You had link which isn't going to work, because link is not the name of a top-level property in that json object. There are properties lower in the hierarchy of your json named "link" but JavaScriptSerializer won't pull out those lower level things into the higher level.
The next property in my GoogleSearchResults class is of type SourceUrl. This is because the url property in the json is not a simple string - it is a json object with two properties, each with a string value. So SourceUrl as a class in C# gets two string properties, each with the appropriate name to deserialize one of those named properties.
the next property in the GoogleSearchResults class is called "items" so that it can deserialize the items dictionary from your json. Now items, as the name suggests, is an array in the json, as denoted by the square bracket around its value. This means there can be more than one item, although in your case there is just one item. So this property in C# must be an array (or collection). Each item in the json result is not a simple string, so, once again, as we did with SourceUrl, we need to define a holder class to deserialize the item object: GoogleSearchItem. This class has a bunch of simple string properties. The properties in the C# class could also be of type int or some other type, if that's what the json requires.
finally, when printing out the result, if you just call Console.WriteLine(result) you will see the result of the ToString() method that is implicitly invoked by Console.WriteLine. This will merely print the name of the type, in this case is "GoogleSearchResults", which is not what you want, I think. In order to see what's in the object, you need to serialize it, as I've shown. In the output of that, you will see only the values of things you deserialized. Using the classes I provided, the result will have less information than the original, because I didn't provide properties in the C# class corresponding to some of the json properties, so those weren't deserialized.
You could take a look at Json.NET and its LINQ support to create and query JSON. By crafting a nice LINQ query you will get only the stuff you need (you can select, group by, count, min, max, whatever you like).
http://msdn.microsoft.com/en-us/library/bb412170.aspx
http://msdn.microsoft.com/en-us/library/bb410770.aspx
Pull out the property you need after you have converted the JSON representation to a type in your C# app. I don't think there's a way to extract only one property from the JSON representation before you have converted it (though I am not sure).

Categories

Resources