Динамическая сериализация и десериализация с использованием JSON в C#

Прежде всего, я думаю, что пытаюсь сериализовать и десериализовать динамически, а не программно. Извините, если ошибся в названии.

Я студент, изучающий программную инженерию, и я пытаюсь немного узнать о JSON. Я создал класс (вероятно, буду использовать его как .dll для своих проектов) для сериализации и десериализации.

    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();
        }
    }

И я называю это так:

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

Вот класс животных:

    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;
        }
    }

Вот класс AnimalList:

    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>();
        }
    }

Это работает отлично до сих пор.

Объект JSON, который я получаю, когда десериализую его, используя

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

is

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

Но я чувствую, что мне не нужно создавать класс AnimalList, чтобы сделать это, но если я этого не сделаю, когда я попытаюсь десериализовать, JSON не знает, как интерпретировать информацию внутри файла JSON. Я не могу понять, как динамически сообщить JSON, что это список животных.

Это содержимое сериализованного файла, созданного с помощью этого метода.

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

Я пробовал без класса AnimalList (просто список‹› животных), и он создает этот файл

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

Итак, он сериализует его, но не знает, как его десериализовать (этот JObject вернет null).

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

Что я делаю не так? Извините, если это слишком длинно; Я старался быть максимально ясным.

Спасибо


person CarlosMira    schedule 28.09.2020    source источник
comment
Он возвращает null, потому что вы сериализуете data (экземпляр AnimalList), и он десериализует тот же тип, который вы пытаетесь преобразовать в JObject (невозможно, поэтому null). Рассмотрите возможность использования универсального Deserialize<T>, который просто вызовет универсальный метод Json.net. Тогда вы можете просто позвонить Deserialize<AnimalList>().   -  person Sinatr    schedule 28.09.2020
comment
Нет-нет, кажется, я неправильно объяснил. Если я использую класс AnimalList, все отлично работает. Проблема заключается в том, что я пытаюсь избежать использования класса AnimalList и просто создаю List‹Animal›, чтобы избежать создания дополнительного класса AnimalList. Я не знаю, я думаю, что это просто лишние строки кода (и то, как выглядит файл json, не похоже на те, которые я вижу везде).   -  person CarlosMira    schedule 28.09.2020
comment
Я перефразирую: чтобы ваш метод Deserialize работал для чего угодно, вам нужно передать в него параметр типа. Если вы знаете тип во время компиляции, то дженерики — самый удобный способ.   -  person Sinatr    schedule 28.09.2020
comment
Если вы сериализуете List<Animal>, вам придется десериализовать его, используя Deserilize<List<Animal>>(). См. это (полагаю, вы используете json.net).   -  person Sinatr    schedule 28.09.2020
comment
Я стараюсь; извините, если я слишком тупой. public object JsonDeserialize<T>(Type dataType, string filePath) звонил из: List<Animal> Animal = jsonParser.JsonDeserialize<List<Animal>>(typeof(List<Animal>), _animalFilePath) as List<Animal>; Объект по-прежнему возвращается null. Я думаю, что слишком усложняю вещи. Я?   -  person CarlosMira    schedule 28.09.2020
comment
@Sinatr Теперь понял, спасибо! public object JsonDeserialize<T>(string filePath) { String JSONtxt = File.ReadAllText(filePath); var obj = JsonConvert.DeserializeObject<T>(JSONtxt); return obj; }   -  person CarlosMira    schedule 28.09.2020


Ответы (1)


Спасибо @Sinatr за помощь. Вот как мне удалось это сделать, не используя классы, действующие как 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;
        }

Затем назовите это так:

Чтобы сохранить в файл

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

Для загрузки из файла:

            // 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>;
            }

Я надеюсь, что это может помочь кому-то еще. Еще раз спасибо @Sinatr.

PS: Если кто-то считает, что я неправ, или есть лучший способ сделать это, пожалуйста, дайте мне знать. Добавьте свой ответ или напишите комментарий. Спасибо.

person CarlosMira    schedule 28.09.2020