-1

First of all, I think I am trying to serialize and deserialize dynamically, not programmatically. Sorry if I made a mistake in the title.

I am a Software Engineering student, and I am trying to learn a bit about JSON. I created a class (I will probably use it as .dll for my projects) to serialize and deserialize.

    public class JSONParser
    {
        public object JsonDeserialize(Type dataType, string filePath)
        {
            JsonSerializer jsonSerializer = new JsonSerializer();

            StreamReader sr = new StreamReader(filePath);
            JsonReader jsonReader = new JsonTextReader(sr);
            JObject obj = jsonSerializer.Deserialize(jsonReader) as JObject;

            jsonReader.Close();
            sr.Close();

            return obj.ToObject(dataType);
        }

        public void JsonSerialize(object data, string filePath)
        {
            JsonSerializer jsonSerializer = new JsonSerializer();

            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            StreamWriter sw = new StreamWriter(filePath);
            JsonWriter jsonWriter = new JsonTextWriter(sw);

            jsonWriter.Formatting = Formatting.Indented;
            jsonSerializer.Serialize(jsonWriter, data);

            jsonWriter.Close();
            sw.Close();
        }
    }

And I call it like so:

                    Animal animal = new Animal
                    {
                        AnimalName = AnimalNameTextBox,
                        AnimalBreed = AnimalBreedTextBox,
                    };

                    AnimalList Animal = new AnimalList ();
                    JSONParser jsonParser = new JSONParser();

                    if (File.Exists(_animalFilePath))
                    {
                        Animal = jsonParser.JsonDeserialize(typeof(AnimalList), _animalFilePath) as AnimalList;
                    }

                    Animal.ListOfAnimals.Add(animal);

                    jsonParser.JsonSerialize(Animal, _animalFilePath);

Here is Animal Class:

    public class Animal
    {
        public string AnimalName { get; set; }
        public string AnimalBreed { get; set; }

        public Animal()
        {
        }

        public Animal(string AnimalName, string AnimalBreed)
        {
            this.AnimalName = AnimalName;
            this.AnimalBreed = AnimalBreed;
        }
    }

Here is AnimalList Class:

    public class AnimalList 
    {
        public List<Animal> ListOfAnimals { get; set; }
        public Animal NewAnimal { get; set; }
        public string AnimalName { get; set; }
        public string AnimalBreed { get; set; }

        public AnimalList()
        {
            ListOfAnimals = new List<Animal>();
        }
    }

It works great so far.

The JSON object I get while I deserialize it using

JObject obj = jsonSerializer.Deserialize(jsonReader) as JObject;

is

{{
  "ListOfAnimals": [
    {
      "AnimalName": "Doggie",
      "AnimalBreed": "Dog"
    }
  ],
  "NewAnimal": null,
  "AnimalName": null,
  "AnimalBreed": null
}}

But, I feel I shouldn't need to create an AnimalList class in order to do this, but if I don't do so, when I try to deserialize, JSON doesn't know how to interpret the information inside the JSON file. I cannot figure it out how to, dynamically, tell JSON that it is a List of Animals.

This is the content of the serialized file created with this method

{
  "ListOfAnimals": [
    {
      "AnimalName": "Doggie",
      "AnimalBreed": "Dog"
    },
    {
      "AnimalName": "Gatito",
      "AnimalBreed": "Cat"
    }
  ],
  "NewAnimal": null,
  "AnimalName": null,
  "AnimalBreed": null
}

I tried without the class AnimalList (just a List<> of Animal), and it creates this file

[
  {
    "AnimalName": "Doggie",
    "AnimalBreed": "Dog"
  }
]

So, it will serialize it but it doesn't know how to deserialize it (this JObject will return null).

JObject obj = jsonSerializer.Deserialize(jsonReader) as JObject;

What am I doing wrong? Sorry if it is too lengthy; I tried to be as clear as possible.

Thanks

ehtio
  • 179
  • 3
  • 11
  • 1
    It returns `null` because you serialize `data` (`AnimalList` instance) and it will deseriaze the same type which you are trying to cast to `JObject` (not possible, therefore `null`). Consider to use generic `Deserialize` which will simply call generic method of Json.net. Then you can simply call `Deserialize()`. – Sinatr Sep 28 '20 at 09:03
  • No no, I think I explained myself wrong. If I use the class AnimalList, everything works great. The problem is when I try to avoid using the class AnimalList, and I just create a List, to avoid creating the extra class AnimalList. I don't know, I think it just extra lines of code (and also the way the json file looks it doesn't look like the ones I can see everywhere else). – ehtio Sep 28 '20 at 09:15
  • 1
    I'll rephrase: to make your `Deserialize` method working for anything, you need to pass type parameter into it. If you know the type at compiler time, then generics is the most convenient way. – Sinatr Sep 28 '20 at 09:17
  • 1
    If you serialize `List`, then you have to deserialize it using `Deserilize>()`. See [this](https://www.newtonsoft.com/json/help/html/DeserializeCollection.htm) (I assume you are using json.net). – Sinatr Sep 28 '20 at 09:23
  • I'm trying; sorry if I am too dumb. `public object JsonDeserialize(Type dataType, string filePath)` called from: `List Animal = jsonParser.JsonDeserialize>(typeof(List), _animalFilePath) as List`; The object still comes back null. I think I am overcomplicating things. Am I? – ehtio Sep 28 '20 at 09:40
  • @Sinatr I got it now, thank you! `public object JsonDeserialize(string filePath) { String JSONtxt = File.ReadAllText(filePath); var obj = JsonConvert.DeserializeObject(JSONtxt); return obj; }` – ehtio Sep 28 '20 at 10:12

1 Answers1

0

Thanks to @Sinatr for his help. This is how I managed to do it without using classes acting as List<>.

        public object JsonDeserialize<T>(string filePath)
        {
            String JSONtxt = File.ReadAllText(filePath);
            var obj = JsonConvert.DeserializeObject<T>(JSONtxt);

            return obj;
        }
        public object JsonDeserialize<T>(string filePath)
        {
            String JSONtxt = File.ReadAllText(filePath);
            var obj = JsonConvert.DeserializeObject<T>(JSONtxt);

            return obj;
        }

Then, call it like so:

To save to File

                    Client client = new Client
                    {
                        ClientName = NameTextBox,
                        ClientAge = Convert.ToInt32(AgeTextBox),
                        ClientStreet = StreetTextBox,
                    };

                    List<Client> ClientList = new List<Client>();
                    JSONParser jsonParser = new JSONParser();    

                    //Check if File exists. If it does, deserialize the file and add the content to the List Client
                    if (File.Exists(_filePath))
                    {
                        ClientList = jsonParser.JsonDeserialize<List<Client>>(_filePath) as List<Client>;
                    }

                    ClientList.Add(client);
                
                    jsonParser.JsonSerialize<List<Client>>(ClientList, _filePath);

To Load from file:

            // First, check if file already exists
            if (!File.Exists(_filePath))
            {
                MessageBox.Show("The file is empty. Please, save some details before trying to load it.");
                return;
            }

            // If file doesn't exist
            else
            {
                JSONParser jsonParser = new JSONParser();
                List<Client> ClientList = jsonParser.JsonDeserialize<List<Client>>(_filePath) as List<Client>;
            }

I hope this can help somebody else. Thanks again to @Sinatr.

PS: If somebody thinks I am wrong, or there is a better way to do it, please let me know. Add your answer or write a comment. Thank you.

ehtio
  • 179
  • 3
  • 11