Convert json to a C# array? - c#

Does anyone know how to convert a string which contains json into a C# array. I have this which reads the text/json from a webBrowser and stores it into a string.
string docText = webBrowser1.Document.Body.InnerText;
Just need to somehow change that json string into an array. Been looking at Json.NET but I'm not sure if that's what I need, as I don't want to change an array into json; but the other way around. Thanks for the help!

just take the string and use the JavaScriptSerializer to deserialize it into a native object. For example, having this json:
string json = "[{Name:'John Simith',Age:35},{Name:'Pablo Perez',Age:34}]";
You'd need to create a C# class called, for example, Person defined as so:
public class Person
{
public int Age {get;set;}
public string Name {get;set;}
}
You can now deserialize the JSON string into an array of Person by doing:
JavaScriptSerializer js = new JavaScriptSerializer();
Person [] persons = js.Deserialize<Person[]>(json);
Here's a link to JavaScriptSerializer documentation.
Note: my code above was not tested but that's the idea Tested it. Unless you are doing something "exotic", you should be fine using the JavascriptSerializer.

using Newtonsoft.Json;
Install this class in package console
This class works fine in all .NET Versions, for example in my project: I have DNX 4.5.1 and DNX CORE 5.0 and everything works.
Firstly before JSON deserialization, you need to declare a class to read normally and store some data somewhere
This is my class:
public class ToDoItem
{
public string text { get; set; }
public string complete { get; set; }
public string delete { get; set; }
public string username { get; set; }
public string user_password { get; set; }
public string eventID { get; set; }
}
In HttpContent section where you requesting data by GET request
for example:
HttpContent content = response.Content;
string mycontent = await content.ReadAsStringAsync();
//deserialization in items
ToDoItem[] items = JsonConvert.DeserializeObject<ToDoItem[]>(mycontent);

Yes, Json.Net is what you need. You basically want to deserialize a Json string into an array of objects.
See their examples:
string myJsonString = #"{
"Name": "Apple",
"Expiry": "\/Date(1230375600000+1300)\/",
"Price": 3.99,
"Sizes": [
"Small",
"Medium",
"Large"
]
}";
// Deserializes the string into a Product object
Product myProduct = JsonConvert.DeserializeObject<Product>(myJsonString);

Old question but worth adding an answer if using .NET Core 3.0 or later. JSON serialization/deserialization is built into the framework (System.Text.Json), so you don't have to use third party libraries any more. Here's an example based off the top answer given by #Icarus
using System;
using System.Collections.Generic;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var json = "[{\"Name\":\"John Smith\", \"Age\":35}, {\"Name\":\"Pablo Perez\", \"Age\":34}]";
// use the built in Json deserializer to convert the string to a list of Person objects
var people = System.Text.Json.JsonSerializer.Deserialize<List<Person>>(json);
foreach (var person in people)
{
Console.WriteLine(person.Name + " is " + person.Age + " years old.");
}
}
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
}
}
}

One Situation that wasn't covered in the other responses is when you don't know the type of what the JSON object contains. That was my case as I needed to be able to NOT type it and leave it dynamic.
var objectWithFields = js.Deserialize<dynamic[]>(json);
Note: it is definitely preferred to have a type, in some cases, it is not possible, that's why I added this answer.

Related

How to access and store a particular object from a json file in c#

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.

How do I deserialize this JSON array (C#)

I am struggling with a subject that has a lot of variants, but I can't seem to find one that works for me, and I think it's because of the way that my JSON array is.
I'm not an expert in C# or JSON, but I already manage to "almost" get this to work. I need to get hand with the class that the JSON will deserialize to.
When I run the code I dont get an error, just a nulls in the xKisokData var.
The JSON data that I am getting. Their are these two different ones.
"{\"Event\": \"sConnection\",\"data[device]\": \"fb16f550-2ef1-11e5-afe9-ff37129acbf4\",\"data[mode]\": \"customer\",\"data[starttime]\": \"2015-07-22T16:07:42.030Z\",\"data[endtime]\": \"\"}"
"{\"Event\": \"Log\",\"data[id]\": \"2015-07-22T16:07:23.063Z\",\"data[messages][0][source]\": \"server\",\"data[messages][0][message]\": \"Server is listening on port 1553\"}"
The code I have so far:
// Read in our Stream into a string...
StreamReader reader = new StreamReader(JSONdataStream);
string JSONdata = reader.ReadToEnd();
JavaScriptSerializer jss = new JavaScriptSerializer();
wsKisokData[] xKisokData = jss.Deserialize<wsKisokData[]>(JSONdata);
My Class:
namespace JSONWebService
{
[DataContract]
[Serializable]
public class KisokEvent
{
public string eventTrigger { get; set; }
}
[DataContract]
[Serializable]
public class KisokData
{
public string data { get; set; }
}
[DataContract]
[Serializable]
public class wsKisokData
{
public KisokEvent KDEvent { get; set; }
public List<KisokData> KDData { get; set; }
}
}
I am sure that I don't understand the Deserialize process. Thanks for the help.
EDIT:
I put the JSON in the top part right from the debugger, here is the strings.
{
"Event": "sConnection",
"data[device]": "fb16f550-2ef1-11e5-afe9-ff37129acbf4",
"data[mode]": "customer",
"data[starttime]": "2015-07-22T16:07:42.030Z",
"data[endtime]": ""
}
{
"Event": "Log",
"data[id]": "2015-07-22T16:07:23.063Z",
"data[messages][0][source]": "server",
"data[messages][0][message]": "Server is listening on port 1553"
}
I would HIGHLY recommend using the json.net package off nuget instead.
You can generate template classes (models) for it by pasting the json into http://json2csharp.com/
Then use said models to convert the json into a c# object (deserializing) by doing a
var jsonStructure = JsonConvert.DeserializeObject<model>(json)
And query as if it was just a standard object
foreach (var x in jsonStructure.KDData)
{
doAction(x.data);
}
// for example

deserialize json without root object to c#/vb.net class

I would like to build a vb.net app that consumes a JSON REST web service. Following, an example of the data that I receive when calling this service:
[
{"id":17552,"title":"Avatar","alternative_title":null,"year":2009},
{"id":31586,"title":"Avatar","alternative_title":"Cyber Wars","year":2004},
{"id":81644,"title":"Aliens vs. Avatars","alternative_title":null,"year":2011}
]
I have tried some tools like json2csharp to generate a class from this example but these tools generate a class like this:
public class RootObject
{
public int id { get; set; }
public string title { get; set; }
public string alternative_title { get; set; }
public int year { get; set; }
}
This class ignores the fact that a list is returned from the service. I assume this is caused by the fact that the json output does not start with a root level object.
What would my c#/vb.net class look like for this json output or should it be parsed "manually"?
You can use Json.Net, and deserialize to array:
var result = JsonConvert.DeserializeObject<RootObject[]>(json_string);
I am not sure what the problem is exactly for you. Using Newtonsoft Json.NET, JsonConvert.DeserializeObject<IEnumerable<RootObject>>(input), i.e. this:
var s = "[{\"id\":17552,\"title\":\"Avatar\",\"alternative_title\":null,\"year\":2009}," +
"{\"id\":31586,\"title\":\"Avatar\",\"alternative_title\":\"Cyber Wars\",\"year\":2004}," +
"{\"id\":81644,\"title\":\"Aliens vs. Avatars\",\"alternative_title\":null,\"year\":2011}]";
var result = JsonConvert.DeserializeObject<IEnumerable<RootObject>>(s);
foreach (var r in result)
Console.WriteLine("{0} - {1}, {2} ({3})", r.id, r.title, r.alternative_title, r.year);
produces the following output for me:
17552 - Avatar, (2009)
31586 - Avatar, Cyber Wars (2004)
81644 - Aliens vs. Avatars, (2011)

Restsharp: Deserialize json object with less/more fields than some class

I'm using Restsharp to deserialize some webservice responses, however, the problem is that sometimes this webservices sends back a json response with a few more fields. I've manage to come around this so far by adding all possible field to my matching model, but this web service will keep adding/removing fields from its response.
Eg:
Json response that works:
{
"name": "Daniel",
"age": 25
}
Matching model:
public class Person
{
public string name { get; set; }
public int age { get; set; }
}
This works fine: Person person = deserializer.Deserialize<Person>(response);
Now suppose the json response was:
{
"name": "Daniel",
"age": 25,
"birthdate": "11/10/1988"
}
See the new field bithdate? Now everything goes wrong. Is there a way to tell to restsharp to ignore those fields that are not in the model?
If there's that much variation in the fields you're getting back, perhaps the best approach is to skip the static DTOs and deserialize to a dynamic. This gist provides an example of how to do this with RestSharp by creating a custom deserializer:
// ReSharper disable CheckNamespace
namespace RestSharp.Deserializers
// ReSharper restore CheckNamespace
{
public class DynamicJsonDeserializer : IDeserializer
{
public string RootElement { get; set; }
public string Namespace { get; set; }
public string DateFormat { get; set; }
public T Deserialize<T>(RestResponse response) where T : new()
{
return JsonConvert.DeserializeObject<dynamic>(response.Content);
}
}
}
Usage:
// Override default RestSharp JSON deserializer
client = new RestClient();
client.AddHandler("application/json", new DynamicJsonDeserializer());
var response = client.Execute<dynamic>(new RestRequest("http://dummy/users/42"));
// Data returned as dynamic object!
dynamic user = response.Data.User;
A simpler alternative is to use Flurl.Http (disclaimer: I'm the author), an HTTP client lib that deserializes to dynamic by default when generic arguments are not provided:
dynamic d = await "http://api.foo.com".GetJsonAsync();
In both cases, the actual deserialization is performed by Json.NET. With RestSharp you'll need to add the package to your project (though there's a good chance you have it already); Flurl.Http has a dependency on it.

Deserializing JSON when fieldnames contain spaces

I'm writing a tool to read JSON files. I'm using the NewtonSoft tool to deserialize the JSOn to a C# class. Here's an example fragment:
"name": "Fubar",
".NET version": "4.0",
"binding type": "HTTP",
The field names contain spaces and other characters (the .) that are invalid in C# identifiers.
What is the correct way to do this?
(Unfortunately I don't have the option of changing the JSON format.)
Use the JsonProperty attribute to indicate the name in the JSON. e.g.
[JsonProperty(PropertyName = "binding type")]
public string BindingType { get; set; }
System.Text.Json
If you're using System.Text.Json, the equivalent attribute is JsonPropertyName:
[JsonPropertyName(".net version")]
public string DotNetVersion { get; set; }
Example below:
public class Data
{
public string Name { get; set; }
[JsonPropertyName(".net version")]
public string DotNetVersion { get; set; }
[JsonPropertyName("binding type")]
public string BindingType { get; set; }
}
// to deserialize
var data = JsonSerializer.Deserialize<Data>(json);
Not sure why but this did not work for me. In this example I simply return a null for "BindingType" every time. I actually found it much easier to just download the Json result as a string and then do something like:
myString = myString.Replace(#"binding type", "BindingType")
You would do this as the step before deserializing.
Also was less text by a tad. While this worked in my example there will be situations where it may not. For instance if "binding type" was not only a field name but also a piece of data, this method would change it as well as the field name which may not be desirable.
If you want to initialize the Json manually, you can do:
var jsonString = "{" +
"'name': 'Fubar'," +
"'.NET version': '4.0'," +
"'binding type': 'HTTP'," +
"}";
var json = JsonConvert.DeserializeObject(jsonString);
return Ok(json);
Don't forget to include using Newtonsoft.Json;

Categories