How do I convert an IEnumerable to JSON? - c#

I have a method that returns an IEnumberable containing 1..n records. How do I convert the results to a JSON string?
Thanks!

IEnumerable<int> sequenceOfInts = new int[] { 1, 2, 3 };
IEnumerable<Foo> sequenceOfFoos = new Foo[] { new Foo() { Bar = "A" }, new Foo() { Bar = "B" } };
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
string outputOfInts = serializer.Serialize(sequenceOfInts);
string outputOfFoos = serializer.Serialize(sequenceOfFoos);
Which produces the output
[1,2,3]
[{"Bar":"A"},{"Bar":"B"}]
And then you can get your sequence back
IEnumerable<Foo> foos = serializer.Deserialize<IEnumerable<Foo>>(outputOfFoos);

Maybe you can try this:
var categories = from c in db.tableone
select new { key = c.tableoneID, value = c.tableoneName };
JsonResult categoryJson = new JsonResult();
categoryJson.Data = categories;
return categoryJson;

You can do it like this using .NET Framework itself and without using any 3rd party tools
using System.Web.Script.Serialization;
public class Json
{
public string getJson()
{
// some code //
var products = // IEnumerable object //
string json = new JavaScriptSerializer().Serialize(products);
// some code //
return json;
}
}

When using MVC you can use the "System.Web.Helpers.Json class". I needed a few items rendered with the page in json:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int Categorie { get; set; }
}
In the view:
#{
var products = new List<Product> {
new Product{ Id = 1, Name = "test product", Categorie = 1},
new Product{ Id = 2, Name = "another product",Categorie = 1},
new Product{ Id = 3, Name = "more stuff",Categorie = 1},
new Product{ Id = 4, Name = "even more",Categorie = 2},
new Product{ Id = 5, Name = "and the last",Categorie = 2}
};
}
//fill the javascript variable with products
var products= #(Html.Raw(Json.Encode(products) ));
Note the Html.Raw...
While this can be helpfull, don't over use it. Rendering large sections of data into your page makes the page large and may cause performance issues when the browser can not cache your results. If you need more data, use a REST call, so the browser can cache the results.

I would look into a 3rd party tool to do the conversion of your objects to JSON. Here is a good one: http://json.codeplex.com/

Related

Serialize and deserialize JSON object from separate classes without need to have stand-alone class?

Is it possible to form an object from two classes and then serialize it to JSON, and when deserialize it back be able to get those two objects.
say I have: an object of Student and a List<Course>
is it possible to combine these two objects in one JSON object.
I need this because building up a class for every JSON object would be very exhausting in the project I'm working on!
Is it possible to form an object from two classes and then serialize it to JSON
Yes it is possible to do this just use Merge from JObject
for example here is an example
class Student
{
public string Name { get; set; }
}
class Course
{
public string Title { get; set; }
}
var std = new Student() {Name = "foo"};
var lstCours = new List<Course>() { new Course(){Title = "math"}};
var stdJson = JsonConvert.SerializeObject(new {student=std});
var lstCoursJson = JsonConvert.SerializeObject( new{Cours= lstCours});
JObject jObjectStd = JObject.Parse(stdJson);
JObject jObjectLstCours = JObject.Parse(lstCoursJson);
jObjectStd.Merge(jObjectLstCours,new JsonMergeSettings(){MergeArrayHandling = MergeArrayHandling.Concat});
Console.WriteLine(jObjectStd.ToString());
here what you get as a merge
{
"student": {
"Name": "foo"
},
"Cours": [
{
"Title": "math"
}
]
}
to deserialize this is pretty simple with JSON.net
var stdParsed = JObject.Parse(json).Property("student").Value.ToString();
var lstCoursParsed = JObject.Parse(json).Property("Cours").Value.ToString();
var stdDes = JsonConvert.DeserializeObject<Student>(stdParsed);
var lstCoursDes = JsonConvert.DeserializeObject<List<Course>>(lstCoursParsed);
Yes, this is possible, and is actually very straightforward to do.
Say you have your two objects like this:
var student = new Student { Name = "Joe Schmoe" };
var courses = new List<Course>
{
new Course { Title = "Underwater Basket Weaving 101" },
new Course { Title = "History of Pancakes 102" }
};
On the serializing side, just use an anonymous object to combine your objects together and then serialize that:
var anon = new { Student = student, Courses = courses };
var json = JsonConvert.SerializeObject(anon, Formatting.Indented);
Here is the JSON you would get:
{
"Student": {
"Name": "Joe Schmoe"
},
"Courses": [
{
"Title": "Underwater Basket Weaving 101"
},
{
"Title": "History of Pancakes 102"
}
]
}
You can combine as many objects together as you need to in this way.
On the flip side, you can deserialize to a dynamic variable (which is a JObject behind the scenes) and then recreate your original strongly-typed objects from it using ToObject<T>().
dynamic obj = JsonConvert.DeserializeObject(json);
var student = obj.Student.ToObject<Student>();
var courses = obj.Courses.ToObject<List<Course>>();
Round-trip demo: https://dotnetfiddle.net/OKJBg2
Alternatively you can use deserialize-by-example to deserialize back to an anonymous object if you don't like the dynamic variable / JObject idea. To do that, you first create an empty anonymous object in the same shape as the JSON to use as a "template" and then pass it along with the JSON to JsonConvert.DeserializeAnonymousType:
var template = new { Student = new Student(), Courses = new List<Course>() };
var anon = JsonConvert.DeserializeAnonymousType(json, template);
Student student = anon.Student;
List<Course> courses = anon.Courses;
Demo: https://dotnetfiddle.net/Inz0r8
Serialize a KeyValuePair<Student, List<Course>> and deserialize to the KeyValuePair again.
var student = ...;
var courses = ...;
var json = JsonConvert.SerializeObject(new KeyValuePair<Student, List<Course>>(student, courses));
Then, deserialize it this way:
var pair = JsonConvert.DeserializeObject<KeyValuePair<Student, List<Course>>>(json);
var student = pair.Key;
var courses = pair.Value;
This is a workaround, but it's easy to understand, and very easy to use (compared to JObject or a class to combine them).
Just Create new Class which has those 2 objects like this
public class StudentWithCours
{
public Student student { get; set; }
public List<Course> course { get; set; }
}
after that you can serialize/deserialize the class exemplar like this
.......
StudentWithCours myObject = new StudentWithCours();
//your some logic here]
var serilizedObject = JsonConvert.SerializeObject(myObject);
var deserilizedObject = JsonConvert.DeserializeObject<StudentWithCours>(serilizedObject);
It is. This one-liner depends on the Newtonsoft NuGet package, which is popular and better than the default serializer.
var myObject = ...;
Newtonsoft.Json.JsonConvert.SerializeObject(myObject);
Documentation: Serializing and Deserializing JSON
Other possibility:
You could use the JavaScriptSerializer class (add reference to System.Web.Extensions):
using System.Web.Script.Serialization;
var json = new JavaScriptSerializer().Serialize(obj);
Other options are available here, where you can find above two answers, along with many others.
Piece of code:
public class Student
{
public string Name { get; set; }
public List<Course> Courses { get; set; } = new List<Course>();
public class Course
{
public string Name { get; set; }
public string Code { get; set; }
}
}
var student = new Student
{
Name = "Jack",
Courses = new List<Student.Course>
{
new Student.Course() {Name = "MATH", Code = "MA"},
new Student.Course() {Name = "Science", Code = "SC"}
}
};
var str = JsonConvert.SerializeObject(student);
var studentDeserialized = JsonConvert.DeserializeObject<Student>(str);
Try it out for yourself

Nested Json array in MVC Controller

Pretty silly question to ask. but could not figure it out .
In a C# MVC Controller action , I need to model a Json Array for testing purposes.
But this shows me compilation errors instead of being a valid Json:
var result = {
"controllerId": "controller1",
"controllerName": "ControllerOne"
};
But this is perfectly valid :
var scheduleResult = new[]
{
new { scheduleId = "schedule1",scheduleName = "scheduleOne"},
new { scheduleId = "schedule2",scheduleName = "scheduleTwo"}
};
Why so ?
Also how to write a nested Json array :
I tried :
var scheduleResult = new[]
{
new { scheduleId = "schedule1",scheduleName = "scheduleOne",new[]{ new {doorId="Door1",doorName="DoorOne"}, new { doorId = "Door2", doorName = "DoorTwo" } } },
new { scheduleId = "schedule2",scheduleName = "scheduleTwo"}
};
But it shows errors in syntax. What to do ?
I Need to have nested array within each element of that array .
Thanks in advance.
Well, C# does not support the way you wrote. You can't just type in JSON in C# and expect it to work unfortunately. You can try like that with anonymous type:
var result = new
{
controllerId = "controller1",
controllerName = "ControllerOne",
myArray = new []
{
"a",
"b"
}
};
This is converted to JSON no problem if you return it as a result of API call.
The nested arrays you are talking about don't work because you need to give them a name, you can't have array property without a name. See example above.
Why don't you use Dictionary<TKey, TValue> with Newtonsoft.Json?
Simple json:
IDictionary<string, string> obj = new Dictionary<string, string>();
obj.Add("controllerId", "controller1");
obj.Add("controllerName", "ControllerOne");
// {"controllerId":"controller1","controllerName":"ControllerOne"}
string json = JsonConvert.SerializeObject(obj);
Nested json:
IList<string> obj = new List<string>();
IDictionary<string, string> first = new Dictionary<string, string>();
first.Add("scheduleId ", "schedule1");
first.Add("scheduleName", "scheduleOne");
IDictionary<string, string> second = new Dictionary<string, string>();
second.Add("scheduleId ", "schedule2");
second.Add("scheduleName", "scheduleTwo");
string first_json = JsonConvert.SerializeObject(first);
string second_json = JsonConvert.SerializeObject(second);
obj.Add(first_json);
obj.Add(second_json);
// ["{\"scheduleId \":\"schedule1\",\"scheduleName\":\"scheduleOne\"}","{\"scheduleId \":\"schedule2\",\"scheduleName\":\"scheduleTwo\"}"]
string json = JsonConvert.SerializeObject(obj);
Here first of all we should create model class with the same pattern of our return type
public class ScheduleModel
{
public List<Schedule> ScheduleList { get; set; }
}
public class Schedule
{
public int ScheduleId { get; set; }
public string ScheduleName { get; set; }
public List<Door> DoorList { get; set; }
}
public class Door
{
public int DoorId { get; set; }
public string DoorName { get; set; }
}
Now at the controller Action create the test data
List<Door> doorList = new List<Door>();
doorList.Add(new Door{DoorId = "Door1",DoorName = "DoorOne"});
doorList.Add(new Door{DoorId = "Door2",DoorName = "DoorTwo"});
List<Schedule> scheduleList = new List<Schedule>();
scheduleList.Add(new Schedule{
ScheduleId = "schedule1",
ScheduleName = "scheduleOne",
DoorList = doorList
});
scheduleList.Add(new Schedule
{
ScheduleId = "schedule2",
ScheduleName = "scheduleTwo",
});
return Json(scheduleList, JsonRequestBehavior.AllowGet);
If this answer benefits you please mark as an answer.

MongoDB C# Get all documents from a list of IDs

I have a list of Ids
List<string> Ids;
and I would like to retrieve all the documents matching these Ids.
There are solutions on the web:
var ids = new int[] {1, 2, 3, 4, 5};
var query = Query.In("name", BsonArray.Create(ids));
var items = collection.Find(query);
but they're all with the old C# driver and with the (not so new anymore) 2.2.4 driver the API has changed and I can't find how to build this query.
please see snippet below (made using LINQPad)
void Main()
{
// To directly connect to a single MongoDB server
// or use a connection string
var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("test");
var collectionEmpInfo = database.GetCollection<Employee>("Employee");
Employee EmpInfo = new Employee
{
EmpID = "103",
EmpName = "John",
CreatedAt = DateTime.Now,
EmpMobile = new List<Mobile>
{
new Mobile{ MobNumber = "55566610", IsPreferred = true, MobID = ObjectId.GenerateNewId() },
new Mobile{ MobNumber = "55566611", IsPreferred = false, MobID = ObjectId.GenerateNewId() },
}
};
//collectionEmpInfo.InsertOne(EmpInfo);
var filterDef = new FilterDefinitionBuilder<Employee>();
var filter = filterDef.In(x=>x.EmpID , new[]{"101","102"});
filter.Dump();
var empList = collectionEmpInfo.Find(filter).ToList();
empList.Dump();
}
public class Employee
{
public ObjectId Id { get; set; }
public string EmpID { get; set; }
public string EmpName { get; set; }
public List<Mobile> EmpMobile { get; set; }
public DateTime CreatedAt { get; set; }
}
public class Mobile
{
public ObjectId MobID { get; set; }
public string MobNumber { get; set; }
public bool IsPreferred { get; set; }
}
and results screenshot
This looks to be the current equivalent of what you were attempting:
var ids = new int[] {1, 2, 3, 4, 5};
var filter = Builders<BsonDocument>.Filter.In("name", ids);
var items = collection.Find(filter);
I struggled with this recently.
Using the new driver (v2.14.X) this can be achieved with the $in operator. This Mongo link describes the $in functionality reasonably well.
You can either apply the LINQ format:
var ids = new List<string> {"id1", "id2", "etc"};
someMongoCollection.Find(o => o.Any(i => ids.Contains(o.Id));
The LINQ format works well except for cases where you're trying to chain queries together (i.e. if you are querying with optional data, so int[] ages, string[] ids, etc.). In that case you effectively want to build up the query as necessary.
For that application I use the native mongo format (also described in the Mongo link above).
{ Id: { $in: ["id1", "id2", "etc"] } }
This is passed as a string to create a BsonDocument which is then used as the filter on the .Find() operation. You can add more filters as necessary. More information on passing in data to create BsonDocument objects can be found at this link.
See example code snip below:
// 1 - init base filter (this fetches everything)
var filter = new BsonDocument();
// 2 - init id data
var ids = new List<string> {"id1", "id2", "etc"};
var idsString = ids.ConvertAll(i => $"\"{i}\"");
// 3 - create the mongo formatted query and generate the BsonDocument
var bsonToParse = $"{{ \"Id\": {{ $in: [{string.Join(",", idsString )}] }} }}";
var idsFilterBson = BsonDocument.Parse(bsonToParse);
// 4 - add the BsonDocument to the already existing filter
filter.Add(idsFilterBson);
// perform steps 2-4 for any other optional query data
// run the final find operation
var dataFromDb = await someMongoCollection.Find(filter).Limit(limit).ToListAsync();
with latest c# mongo driver you also can leverage LINQ support:
var results = this.mongoClient.GetCollection<Employee>()
.AsQueryable()
.Where(x => idList.Contains(x.Id))
.ToList();

Mixing in new fields to an object without hard-coding its fields in a LINQ query?

I have a simple LINQ query here:
var Staffs = new[]
{
new { id = 1, name = "Jefferson", age = 42},
new { id = 2, name = "Jacobson", age = 54},
new { id = 3, name = "Zhang", age = 34}
};
var payroll = new[]
{
new { pid = 1, wage = 5000},
new { pid = 2, wage = 6500},
new { pid = 3, wage = 6700}
};
var q = from stf in Staffs
from pay in payroll
where stf.id == pay.pid
select new
{
stfObj = stf,
pay.pid,
pay.wage
};
Here, stfObj would be an object containing the id, name and age fields
Here comes the question:
Is it possible to turn the object into the fields themselves without explicitly hard-coding the field names like this:
select new
{
stf.id,
stf.name,
stf.age,
pay.pid,
pay.wage
};
In this way, there will be no need to change the select new block when I add a new field to Staffs, like Gender for example
Is that possible?
(ok, this looks like the question here... anyway, hoping to get better answers here)
Is this what you want!
select new
{
sId=stfObj.id,
sName=stfObj.name,
sAge=stdObj.age,
pId=pay.pid,
pWage=pay.wage
};
Why not simply embed your object ?
select new {
staff = stf,
pay = pay
};
I do not know, what you need this for. But you could try to use Dictionary<> for this. Say, we have a class:
public class Test
{
public string Name { get; set; }
public string Desc { get; set; }
}
So you can do the following:
List<Test> list = new List<Test>
{
new Test
{
Name = "Test 1",
Desc = "Desc 1"
}
};
var temp = list.Select(t =>
{
Dictionary<string, object> values = new Dictionary<string, object>();
foreach (PropertyInfo pi in t.GetType().GetProperties())
values[pi.Name] = pi.GetValue(t, null);
return values;
})
.FirstOrDefault();
temp.ToList().ForEach(p => Console.WriteLine(string.Format("{0}:\t{1}", p.Key, p.Value)));
So if you add a property to the Test class, say, like this:
public bool Extra { get; set; }
You'll get it in the dictionary automatically. Probably you'll have to work with reflection methods overloads to get exactly what you need...

get elements from list based on another list

I got two classes, like:
public class Person
{
public long Id { get; set; }
public string Name { get; set; }
}
public class Vampire
{
public long Id { get; set; }
}
Then, I have two lists, a list of persons and a list of vampires. All vampires are persons.
What I need is two children lists of persons, infected and notInfected. I'm building the two lists with a for, but I know it's possible using linq or something.
Any help?
Something like this:
var vampireIds = new HashSet<long>(vampireList.Select(x => x.Id));
var infectedPersons = personList.Where(x => vampireIds.Contains(x.Id));
var regularPersons = personList.Where(x => !vampireIds.Contains(x.Id));
I would go with something like the following:
void Main()
{
var list = new List<Person>(){ new Person(){ Id = 1 }, new Vampire(){ Id = 2 } };
var infected = list.Where (x => x is Vampire);
var notInfected = list.Except(infected);
}
public class Person
{
public long Id { get; set; }
public string Name { get; set; }
}
public class Vampire : Person
{
}
If only a person can be a Vapire, you could inherit Vampire from Person and then iterate through all persons and see if they are Vampires; if yes -> add to Vampire list, otherwise to non-Vampire list.
Try this:
var people = new List<Person>
{
new Person {Id = 1, Name = "John"},
new Person {Name = "Dave", Id = 2},
new Person {Id = 3, Name = "Sarah"}
};
var vamps = new List<Vampire> {new Vampire {Id = 1}};
var theInfected = people.Where(p => vamps.Select(v => v.Id).Contains(p.Id));
var theAfraid = people.Except(theInfected);
foreach (var person in theInfected)
{
System.Console.WriteLine(person.Name + " Is Infected!");
}
foreach (var person in theAfraid)
{
System.Console.WriteLine(person.Name + " Is Afraid!");
}
Hope it's helpful.

Categories

Resources