Search code examples
jsonlistserializationjson.netdeserialization

How to use newtonsoft.Json to serialize and deserialize multiple objects into and out of a list


So I am practising using newtonsoft.Json by creating a very simple Register.

In this code a user enters a first name and last name and this is put into my very simple Person object, which is then put into a List

The user can add multiple people and they are put into the List

My code isn't working and I need help because I am learning.

It isn't working because the serialization and deserialization process is coded wrong I think.

At the beginning of the code a List is declared with the People from the json file

List<Person> AllPeopleAdded = new List<Person>(JsonConvert.DeserializeObject<List<Person>>(File.ReadAllText(jsonfilePath)));

This is the code showing how the people are added to the json file

File.AppendAllText(jsonfilePath,JsonConvert.SerializeObject(PeopleAddedThisTime));

This is the full code

using System;
using System.Collections.Generic;
using System.IO;
using OOP__Data_Entry__homework.Classes.Person;
using Newtonsoft.Json;
namespace OOP__Data_Entry__homework
{
    class Program
    {
        const string FirstNameText = "Enter A First Name";
        const string LastNameText = "Enter A Last Name";
        const string ContinueText = "Would you Like to Add Another Person, Yes or No";
        const string YesResponse = "Yes";
        const string NoResponse = "No";
        const string ContinueErrorText = "Enter Yes or No";
        const string jsonfilePath = @"C:\OOP- Data Entry- homework\PeopleSaved.json";
        static void Main(string[] args)
        {
            //done so that line 29 can work, without swaure brackets there is no list for the List (AllPeopleAdded) to take in
            if(File.Exists(jsonfilePath))
            {
            }
            else
            {
                File.WriteAllText(jsonfilePath,"[]");
            }

            List<Person> AllPeopleAdded = new List<Person>(JsonConvert.DeserializeObject<List<Person>>(File.ReadAllText(jsonfilePath)));
            List<Person> PeopleAddedThisTime = new List<Person>();

            //done so that the jsonfile(PeopleSaved.json) doesnt error after the new People are added when the user says they do not want to add any more people (line 57)
            if(File.ReadAllText(jsonfilePath).StartsWith("[]"))
            {
                File.WriteAllText(jsonfilePath,"");
            }

            string FirstName;
            string LastName;
            while(true)
            {
                System.Console.WriteLine(FirstNameText);
                FirstName=Console.ReadLine();
                
                System.Console.WriteLine(LastNameText);
                LastName = Console.ReadLine();

                Person newPerson = new Person(FirstName,LastName);
                PeopleAddedThisTime.Add(newPerson);

                System.Console.WriteLine(ContinueText);
                while(true)
                {
                    string response = Console.ReadLine();
                    if (response==YesResponse)
                    {
                        break;
                    }
                    else if (response == NoResponse)
                    {
                        File.AppendAllText(jsonfilePath,JsonConvert.SerializeObject(PeopleAddedThisTime));
                        foreach(Person allPersons in AllPeopleAdded)
                        {
                            System.Console.WriteLine($"\n {allPersons.GetFullName()}");
                        }
                        foreach(Person newPersons in PeopleAddedThisTime)
                        {
                            System.Console.WriteLine($"\n {newPersons.GetFullName()}");
                        }
                        return;
                    }
                    else
                    {
                        System.Console.WriteLine(ContinueErrorText);
                    }
                }
            }
        }
    }
}

This is the json file after the code is run once

[{"mFirstName":"john ","mLastName":"doe"},{"mFirstName":"Josh","mLastName":"Smith"}]

This is the json file after the code is run again (It is formatted wrong-that is a problem)

[{"mFirstName":"john ","mLastName":"doe"},{"mFirstName":"Josh","mLastName":"Smith"}][{"mFirstName":"Serge","mLastName":"Superhero"}]

The Person Class

using System;

namespace OOP__Data_Entry__homework.Classes.Person
{
    class Person
    {
        public string mFirstName {get; private set; }
        public string mLastName {get; private set; }

        public Person(string firstName, string lastName)
        {
            mFirstName = firstName;
            mLastName = lastName;
        }
        public string GetFullName()
        {
            return mFirstName+" "+mLastName;
        }
    }
}

What the json file looks after a couple times the code is run using serge's code

[{"mFirstName":null,"mLastName":null},{"mFirstName":null,"mLastName":null},{"mFirstName":"f","mLastName":"f"}]

Solution

  • You have to deserialize existing json into list, add new person to existing users lists ( or maybe remove some) and after this to serialize the whole list again. Using append will never work, since json always must have only one root element, and you have to insert a new data inside of this root. But you are trying to add the second root and that makes json invalid.

        string json = string.Empty;
        using (StreamReader r = new StreamReader(jsonfilePath))
            json = r.ReadToEnd();
    
     List<Person> AllPeopleAdded = JsonConvert.DeserializeObject<List<Person>>(json);
    
    List<Person> PeopleAddedThisTime = new List<Person>();
        
            
        //.....
        
        AllPeopleAdded.AddRange(PeopleAddedThisTime);
    
        using (StreamWriter file = File.CreateText(jsonfilePath))
        {
            JsonSerializer serializer = new JsonSerializer();
            serializer.Serialize(file, AllPeopleAdded);
        }
    
     // or  serialize JSON to a string and then write string to a file
    File.WriteAllText(jsonfilePath, JsonConvert.SerializeObject(AllPeopleAdded));
    

    and fix person class

    public class Person
    {
        public string mFirstName { get; private set; }
        public string mLastName { get; private set; }
        
        [JsonConstructor]
        public Person(string mFirstName, string mLastName)
        {
            this.mFirstName = mFirstName;
            this.mLastName = mLastName;
        }
        public string GetFullName()
        {
            return mFirstName + " " + mLastName;
        }
    }