1

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!

mshwf
  • 7,009
  • 12
  • 59
  • 133
  • I now see that I misinterpreted your question a little. Since the (de)serializer map everything on properties/fields, you'd probably want to create a wrapper object, like @Vecchiasignora said. Otherwise the deserializer wouldn't know what to deserialize to which object. – stealthjong Jul 26 '17 at 13:00
  • @stealthjong using a KeyValuePair also solves the problem – Mafii Jul 26 '17 at 13:02
  • @mafii Only in the case that you have only two objects to serialize. Otherwise you'd still have to fallback on a wrapper object – stealthjong Jul 26 '17 at 13:04
  • @stealthjong there are also tuples. It's ugly I know, but he specified that he doesn't want to create a wrapper... – Mafii Jul 26 '17 at 13:05
  • @Mafii I know, but that's just plain dumb. For the sake of not creating a wrapper class, you're jumping through hoops everywhere. And it isn't helping readability too. You'd almost be better off serializing everything manually. That way you also don't have to create a wrapper class, and because of the key you should know in how to deserialize. But that wouldn't make sense, and neither does using KVpairs and tuples to serialize/deserialize. BRAHIM Kamel's code already isn't readable anymore. – stealthjong Jul 26 '17 at 13:24

5 Answers5

2

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); 
BRAHIM Kamel
  • 13,492
  • 1
  • 36
  • 47
2

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

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
  • but I'll need to use `JObject` to deserialize it back? – mshwf Jul 26 '17 at 21:24
  • The dynamic object actually *is* a `JObject` behind the scenes, so yes. Alternatively, you could deserialize back to an anonymous object using deserialize-by-example if you don't want the `dynamic` / `JObject`. – Brian Rogers Jul 26 '17 at 21:29
  • 1
    This seems like the best solution. All other solutions result in de facto the same, but with more confusing or redunant code compared to this solution. +1 – Mafii Jul 27 '17 at 07:06
1

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

Mafii
  • 7,227
  • 1
  • 35
  • 55
0

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);
Vecchiasignora
  • 1,275
  • 7
  • 6
-1

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

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
stealthjong
  • 10,858
  • 13
  • 45
  • 84