This question already has answers here:
How can I deserialize JSON with C#?
(19 answers)
Closed 3 years ago.
I'm looking to utilise a 3rd party service to authenticate, retrieve data and display it on a page.
The data would be returned in JSON format and will use HttpWebRequest to make the call.
I have got all the JSON URLs that I will use and converted them to C# classes using an online converter.
I am now trying to find a serialiser/deserialiser to convert the data into C# objects so I can hook the control with the data retrieved.
After some research, I'm confused if I should go with JsonConvert or Newtonsoft? Some have decided to create their own but I'm only repeating the wheel going down this road.
There's quite a number of articles but I rather invest some time in a more supported tool/version.
Does anyone know what/which serialiser and deserialiser I could look into for the task above?
I won't be using MVC but Asp webforms so not sure if that makes a difference. Would appreciate any examples of the tool to show how it would convert the data either way?
Edit 1
Result of sample data from answer converted to C# class
public class RootObject
{
public int itemId { get; set; }
public string itemName { get; set; }
}
I always use Newtonsoft.Json library for mapping json data to an object, I personally use JsonConvert static class since it is easier to implement, here's how I do when mapping the json to object:
Sample Json:
[
{
"itemId": 1
"itemName": "Item 1"
},
{
"itemId": 2
"itemName": "Item 2"
},
.
.
.
]
Sample Object:
public class ItemData
{
[JsonProperty("itemId")]
public string ItemId { get; set; }
[JsonProperty("itemName")]
public string ItemName { get; set; }
}
Json convert:
var serializeItem = JsonConvert.SerializeObject(yourJsonObjectHere); // serialize object
var deserializeItem = JsonConvert.DeserializeObject<List<ItemData>>(yourJsonHereObject); // deserialize object
It is base on your personal preference and I think (IMHO) that JsonConvert is much easier to use.
Related
C#
Let's say that I want to make a winform page that receives a certain amount of random features read from the contents of a json file. (while using the 'Newtonsoft.Json' library)
Code that Deserializes the json file
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(File.ReadAllText(#"..\..\Json\features.json"));
These classes are set to represent the contents and structure of the json file within the same c# file, but outside of the main class of course.
class Root
{
public List<Category> category { get; set; }
}
class Category
{
public string name { get; set; }
public List<Feature> feature { get; set; }
}
class Feature
{
public string name { get; set; }
public string frequency { get; set; }
}
I have followed the practices to make this happen here:
https://www.newtonsoft.com/json/help/html/DeserializeWithJsonSerializerFromFile.htm
Can not deserialize JSON with array in array
https://json2csharp.com/
It works, however there are two main problems I can see with this:
It can end up visually cluttering the .cs file with lots of classes that you'll never need to look or edit, especially when it is interpreting multiple json files
It isn't dynamic, and it will only work for one json file that you have to make compatible by creating these classes for every subclass that exists within the json file.
My question: Is there a way to deserialize the json file without having to resort to creating multiple classes for every sub-category of data in the json string?
I believe you don't need the classes, because you don't need the whole JSON string, is that correct?
If so, instead of deserializing the whole json file, you could partially deserialize only the parts which you are interested in.
Have a look at this example from the Newtonsoft.Json documentation, where we have a long json string representing a response from a Google search, but are only interested in the responseData/results part of it, and only in some fields of that result object:
Object to partially desierialize:
public class SearchResult
{
public string Title { get; set; }
public string Content { get; set; }
public string Url { get; set; }
}
Deserializing Partial JSON Fragment Example:
string googleSearchText = #"{
'responseData': {
'results': [
{
'GsearchResultClass': 'GwebSearch',
'unescapedUrl': 'http://en.wikipedia.org/wiki/Paris_Hilton',
'url': 'http://en.wikipedia.org/wiki/Paris_Hilton',
'visibleUrl': 'en.wikipedia.org',
'cacheUrl': 'http://www.google.com/search?q=cache:TwrPfhd22hYJ:en.wikipedia.org',
'title': '<b>Paris Hilton</b> - Wikipedia, the free encyclopedia',
'titleNoFormatting': 'Paris Hilton - Wikipedia, the free encyclopedia',
'content': '[1] In 2006, she released her debut album...'
},
{
'GsearchResultClass': 'GwebSearch',
'unescapedUrl': 'http://www.imdb.com/name/nm0385296/',
'url': 'http://www.imdb.com/name/nm0385296/',
'visibleUrl': 'www.imdb.com',
'cacheUrl': 'http://www.google.com/search?q=cache:1i34KkqnsooJ:www.imdb.com',
'title': '<b>Paris Hilton</b>',
'titleNoFormatting': 'Paris Hilton',
'content': 'Self: Zoolander. Socialite <b>Paris Hilton</b>...'
}
],
'cursor': {
'pages': [
{
'start': '0',
'label': 1
},
{
'start': '4',
'label': 2
},
{
'start': '8',
'label': 3
},
{
'start': '12',
'label': 4
}
],
'estimatedResultCount': '59600000',
'currentPageIndex': 0,
'moreResultsUrl': 'http://www.google.com/search?oe=utf8&ie=utf8...'
}
},
'responseDetails': null,
'responseStatus': 200
}";
// Parse JSON into a JObject, which we can easily traverse
JObject googleSearch = JObject.Parse(googleSearchText);
// get JSON result objects into a list
IList<JToken> results = googleSearch["responseData"]["results"].Children().ToList();
// serialize JSON results into .NET objects
IList<SearchResult> searchResults = new List<SearchResult>();
foreach (JToken result in results)
{
// JToken.ToObject is a helper method that uses JsonSerializer internally
SearchResult searchResult = result.ToObject<SearchResult>();
searchResults.Add(searchResult);
}
// Title = <b>Paris Hilton</b> - Wikipedia, the free encyclopedia
// Content = [1] In 2006, she released her debut album...
// Url = http://en.wikipedia.org/wiki/Paris_Hilton
// Title = <b>Paris Hilton</b>
// Content = Self: Zoolander. Socialite <b>Paris Hilton</b>...
// Url = http://www.imdb.com/name/nm0385296/
This way, we only need to create a class for SearchResult and for nothing else, which sounds like what you want to have. While traversing the JSON object with code like googleSearch["responseData"]["results"] you can check whether the result is null and act accordingly, which means you can have optional fields in your JSON file, which are not present in other files, without your code breaking.
Does this help you solve your issues?
I believe that best practice is using classes.
Here are my arguments for using classes in your case:
You can read json bit by bit, use JObject.Parse or even dynamic (ugh) but it think your code should depend on a class (a dto) not on a json string. This input structure happens to be stored in json, but may not be. Most of your unit tests should take in an object, not a string.
I find the argument of deserialising to classes not being dynamic weak because you need to write the code that will handle the added elements. In other words if you add a new feature to json it won't just work, you need to write the code to support it and each time you change the json structure you need to update your code anyway.
I am trying to retrieve JSON data from an API, but one of the property names comes as #data.context . It is not a nested property. I've tested it with ExpandoObject as well, it is exactly like that. Normally in C # I would make a data model like
public class Data
{
public string #odata.context { get ; set; }
}
But this doesn't work, as C# doesn't let me have a comma in the variable name, nor have quotes around it. The # sign is already there
The JSON is as follows: this property that contains a link and then another one that contains a list of objects.
{
"#odata.context": "some link here",
"list" [ {}, {}
]
}
The list of objects do not give me any trouble, only the first property.
You can use JsonPropertyName attribute to map the json to the property e.g:
[JsonPropertyName("#odata.context")]
public string DataContext { get ; set; }
Microsoft docs
You might be consuming a poorly designed API. There are API specifications that tells how to structure and name JSON keys.
One way you can accomplish is
1 Fetch JSON response from API
2 Replace "#data.context" with "Context" or something similar in JSON string
3 Create class with property
public class Data
{
public string Context { get ; set; }
}
4 Deserialise it
I am trying to make a multi-subject quiz game for children using unity3D and questions and answers are stored in a json file. Now i want to create an object named "science" and "maths" and want to store their respective questions in them and when i want to access science i could loop and find and just store the science question in my string instead of reading the whole json file.
here is my json file.
Science ={
"CourseName":"Science",
"No_Of_Ques":4,
"Ques_Data":[
{ "Quesion":"which is the biggest planet in the solar system?",
"Answer":"jupiter",
"options":["mars","earth","venus","jupiter"]
},
{ "Quesion":"How many planets are there in solar system?",
"Answer":"Eight",
"options":["Seven","Nine","Five","Eight"]
},
{ "Quesion":"which is the closest planet to the sun?",
"Answer":"mercury",
"options":["mars","saturn","venus","mercury"]
},
{ "Quesion":"How many moons does jupiter have?",
"Answer":"12",
"options":["5","13","9","12"]
}
]
}
and this is how i have been acessing it so far
path = Application.dataPath + "/QnA.json";
string json = File.ReadAllText(path);
Course c1 = JsonUtility.FromJson<Course>(json);
return c1;
Course and needed serializable Classes:
[Serializable] public class Course
{
public string CourseName;
public string No_Of_Ques;
public QnA[] Ques_Data;
}
[Serializable]
public class QnA
{
public string Quesion;
public string Answer;
public string[] options;
}
i have tried so many things like Deserialization and Jobject asset but none of them seem to work and every implementation that i have found on the internet has the json data in the same file as the c# code but i can not do that as my json contains hundreds of lines of data. kindly help me out a little.
Create a course class in which create getter and setter functions for all of your json keys, for example:
if your json file is like that:
[
{
"CourseName": "Science",
"No_Of_Ques": 1,
...
},
{
"CourseName": "Math",
"No_Of_Ques": 1,
...
}
]
then course class should be:
public class Course
{
public string CourseName { get; set; }
public int No_Of_Ques { get; set; }
}
In your main class or anywhere you can access your selected course, here i am using only 0 index of a json, you can also loop through whole json and find your desirable course.
StreamReader to read a file
convert it to json
Deserialize the json as per your course
Console it
using (StreamReader r = new StreamReader("../../../js.json"))
{
string json = r.ReadToEnd();
List<Course> ro = JsonSerializer.Deserialize<List<Course>>(json);
Console.WriteLine(ro[0].CourseName);
}
I added json file in the same dire where my mainClass file is, as StreamReader requires an absolute path therefore I used an absoulte path for my json file.
using (StreamReader r = new StreamReader("../../../js.json"))
Require Libs
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
Note: I created a console app, not sure your app type
If you want to store multiple courses in your file you will need to store them as json array (as you do with questions):
[
{
"CourseName":"Science",
"No_Of_Ques":1,
"Ques_Data":[
{
"Question":"which is the biggest planet in the solar system?",
"Answer":"jupiter",
"options":[
"mars",
"jupiter"
]
}
]
},
{
"CourseName":"Math",
"No_Of_Ques":1,
"Ques_Data":[
{
"Question":"2 + 2",
"Answer":"4",
"options":[
"4",
"0"
]
}
]
}
]
then you can deserialize them with next structure(for example):
public class Course
{
[JsonProperty("CourseName")]
public string CourseName { get; set; }
[JsonProperty("No_Of_Ques")]
public long NoOfQues { get; set; }
[JsonProperty("Ques_Data")]
public QuesDatum[] QuesData { get; set; }
}
public class QuesDatum
{
[JsonProperty("Question")]
public string Question{ get; set; }
[JsonProperty("Answer")]
public string Answer { get; set; }
[JsonProperty("options")]
public string[] Options { get; set; }
}
var courses = JsonConvert.DeserializeObject<List<Course>>(jsonString);
var course = courses.Where(...).FirstOrDefault();
Or try to use json path:
var course = JToken.Parse(jsonString)
.SelectToken("$[?(#.CourseName == 'Math')]")
.ToObject<Course>();
As for jsonString you can obtain it in any way, reading from file for example.
P.S.
There was typo "Quesion" -> "Question"
To serialize and deserialize objects you have to create a C# class (in your case should be Course class) that can be [Serializable].
First your Json should be a valid one, which it is, you can validate it here.
To serialize and deserialize you can use JsonUtility to certain point, cause it doesn't deserialize jagged arrays, complex objects etc. I recommend to use third party softwares like Newtonsoft or implement your own serialization/deserialization method for your way.
Edit:
Your JSON file should be without the "Science=" part, should look like:
{
"CourseName":"Science",
"No_Of_Ques":4,
"Ques_Data":[
{ "Quesion":"which is the biggest planet in the solar system?",
"Answer":"jupiter",
"options":["mars","earth","venus","jupiter"]
},
{ "Quesion":"How many planets are there in solar system?",
"Answer":"Eight",
"options":["Seven","Nine","Five","Eight"]
},
{ "Quesion":"which is the closest planet to the sun?",
"Answer":"mercury",
"options":["mars","saturn","venus","mercury"]
},
{ "Quesion":"How many moons does jupiter have?",
"Answer":"12",
"options":["5","13","9","12"]
}
]
}
Edit:
For your comment I think you got a misunderstood of how to handle the relation between files and variables.
You want to have (or at least it seems like this) one file for every type of course, so in this case, the text above will be your Science.json file.
When you store that information, you will do similar of what you do:
path = Application.dataPath + "/QnA.json";
string json = File.ReadAllText(path);
Course scienceCourse = JsonUtility.FromJson<Course>(json); //notice the name of the variable!
So as you can see for the variable name, you will read EVERY SINGLE JSON for every course.
The other way to do that, is to store all the courses on the same Json file, and then get them as an ARRAY of Courses -> Course[] allCourses
Using Science={...} to define your object is where you get confused about object definitions. It is not a Science object. It is a Course object.
It should be more like
{
"Courses" :
[
{
"CourseName" : "Science",
...
},
{
"CourseName" : "Maths",
...
}
]
}`.
Wrap it with:
"Quiz" :
{
"Courses" :
[
{
"CourseName" : "Science",
...
},
{
"CourseName" : "Maths",
...
}
]
}
and use
[Serializable]
public class Quiz
{
public Course[] courses;
}
To hold it as a C# object.
From here you can access your courses by quiz.Courses[0].Questions[17] or write helper methods in Quiz class to call courses by enums like quiz.GetCourse(CourseCategory.Science).Questions[8].
I also suggest using Questions instead of Question_Data. That is more object friendly and helps you semantically.
As an additional suggestion, instead of dumping all of the quiz in a single JSON, you may consider sending a single Course object depending on the course, requested using a query like http://myquizserver.com/quiz.php?course=science. Since you mentioned hundreds of lines of JSON, you may also consider getting data question by question.
I have a C#/ASP.Net project using WebAPI2 that has an API endpoint. That endpoint provides an array of JSON objects as a response to a GET request. I use a Model of the native object for serialisation, which is the standard way in WebAPI2 as I understand it.
The serialization happens 'behind the scenes' when I send an OK HttpActionResult typed for an IEnumerable of models,
return Ok<IEnumerable<Model>>(arrayOfModels);
I have a second app that receives the JSON string representation of the array of models. The inbound string to deserialise looks like this, for an array with a single element...
[
{
"ExecID": "EXWB4KT-1",
"Symbol": "CERT-EUR-TEST",
"ExecutionTime": "2016-07-28T14:59:56.24",
"BuyExchID": "IDH64KT-1",
"SellExchID": "IDH64KT-3",
"Tradable": {
"CERT": {
"AccSrc": "ANDY-CERT",
"AccDst": "HIBLET-CERT",
"Qty": "0.01000000",
"State": "PENDING"
},
"EUR1": {
"AccSrc": "HIBLET-EUR",
"AccDst": "ANDY-EUR",
"Qty": "0.33",
"State": "PENDING"
}
}
}
]
How should I rehydrate the JSON data, bearing in mind that I have the WebAPI2 model available in another project?
As I have control of both ends, I am thinking the deserialisation back into an array of models should be trivial, but I am not sure how to do it. I know there are lots of possible ways to do this, I am looking for the sanest or cleanest way.
Try the Newsoft.Json nuget package. Then it's a matter of creating your model and deserializing. Something like this:
public class MyObject
{
int ExecID { get; set; }
string Symbol { get; set; }
//etc etc
}
Then in your method:
using Newtonsoft.Json;
public class MyMethod(string json)
{
List<MyObject> objList = JsonConvert.DeserializeObject<List<MyObject>>(json);
}
This code may not be exact, but should be something similar
I have about 7000 lines of JSON data that I want to parse. An example of just part of it can be seen here. What I did was use WebRequest and StreamReader to put all the data into a string. (Oddly, it puts all of the data into one VERY long line). But now I want to parse this and I am not sure how. Can anyone explain how to use Deserialize? I have parsed JSON data with Java before but I am having trouble doing so with C# especially with my inability to find documentation with clear examples. Any help will be greatly appreciated.
Try JSON.Net, if you have not seen this it should help you.
Json.NET library makes working with
JSON formatted data in .NET simple.
Key features include a flexible JSON
serializer to for quickly converting
.NET classes to JSON and back again,
and LINQ to JSON for reading and
writing JSON.
Deserialization discussed here.
The quickest method of converting
between JSON text and a .NET object is
using the JsonSerializer. The
JsonSerializer converts .NET objects
into their JSON equivalent and back
again.
The basic code structure for deserialization is below - Target still needs to be filled out to capture the rest of the parsed data items with the appropriate type. The file mentioned json.txt contains your data from the URL above.
using System;
using System.IO;
using Newtonsoft.Json;
public class NameAndId
{
public string name;
public int id;
}
public class Data
{
public NameAndId[] data;
}
public class Target
{
public string id;
public NameAndId from;
public Data likes;
}
public class Program
{
static void Main(string[] args)
{
string json = File.ReadAllText(#"c:\temp\json.txt");
Target newTarget = JsonConvert.DeserializeObject<Target>(json);
}
}
Here is the first part of the JSON stream for reference:
{
"id": "367501354973",
"from": {
"name": "Bret Taylor",
"id": "220439"
},
"message": "Pigs run from our house in fear. Tonight, I am wrapping the pork tenderloin in bacon and putting pancetta in the corn.",
"updated_time": "2010-03-06T02:57:48+0000",
"likes": {
"data": [
{
"id": "29906278",
"name": "Ross Miller"
},
{
"id": "732777462",
"name": "Surjit Padham"
},
Personally I don't like carrying around dependencies on external libraries when the functionality is provided by the framework. In this case, the JavaScriptSerializer class:
var serializer = new JavaScriptSerializer();
var myobj = serializer.Deserialize<MyType>(mystring);