1

So, I'm reading a book about .NET Core 3 and I'm at a section where I'm learning how to serialize JSON files. I have run into a problem with types that I haven't been able to figure out a solution to. I have tried working around it, but then I run into other type issues. The problem I get with the code below is CS0029 in the last using statement of Main at File.Create(jsonPath):

Cannot implicitly convert type 'System.IO.FileStream' to 'System.IO.StreamWriter'

I have tried changing the using statement to use a FileStream type instead of a StreamWriter, as per the example I got from Microsoft documentation, but that produces an error at the jsonStream variable on the jsonSerializer.Serialize(jsonStream, people) line that says:

Cannot convert from 'System.IO.FileStream' to 'System.IO.TextWriter

Here is the code below:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
using Packt.Shared;
using static System.Console;
using static System.Environment;
using static System.IO.Path;

namespace WorkingWithSerialization
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Person> people = new List<Person>
            {
                new Person(30000M)
                {
                    FirstName = "Adam",
                    LastName = "Smith",
                    DateOfBirth = new DateTime(1756,12,12)
                },
                new Person(40000M)
                {
                    FirstName = "Lisa",
                    LastName = "Simpson",
                    DateOfBirth = new DateTime(1980,4,30)
                },
                new Person(20000M)
                {
                    FirstName = "Barney",
                    LastName = "Rubble",
                    DateOfBirth = new DateTime(1962,7,14),
                    Children = new HashSet<Person>
                    {
                        new Person(0M)
                        {
                            FirstName = "Bob",
                            LastName = "Rubble",
                            DateOfBirth = new DateTime(1986,5,3)
                        },
                        new Person(0M)
                        {
                            FirstName = "Bamm-Bamm",
                            LastName = "Rubble",
                            DateOfBirth = new DateTime(1984,3,15)
                        }
                    }
                }
            };

            XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<Person>));
            string path = Combine(CurrentDirectory, "people.xml");
            using(FileStream stream = File.Create(path))
            {
                xmlSerializer.Serialize(stream,people);
            }
            WriteLine($"Wrote {new FileInfo(path).Length} bytes to {path}.");
            WriteLine($"\n{File.ReadAllText(path)}");

            using(FileStream xmlLoad = File.Open(path, FileMode.Open))
            {
                List<Person> loadedPeople = (List<Person>)xmlSerializer.Deserialize(xmlLoad);
                foreach(Person person in loadedPeople)
                {
                    WriteLine($"{person.FirstName} has {person.Children.Count} children.");
                }
            }

            string jsonPath = Combine(CurrentDirectory, "people.json");
            using(StreamWriter jsonStream = File.Create(jsonPath))
            {
                var jsonSerializer = new Newtonsoft.Json.JsonSerializer();
                jsonSerializer.Serialize(jsonStream, people);
            }
        }
    }
}

I have also included the newest version of Newtonsoft.Json within the .csproj file, but I don't believe that to be the issue.

I have also tried different ways of casting with no positive results. I am unsure of what it is that I am doing wrong.

  • 1
    https://learn.microsoft.com/en-us/dotnet/api/system.io.streamwriter.-ctor?view=netframework-4.8#System_IO_StreamWriter__ctor_System_IO_Stream_ – Retired Ninja Apr 16 '20 at 01:15

2 Answers2

0

You need an extra step to create a StreamWriter that uses the FileStream.

string jsonPath = Combine(CurrentDirectory, "people.json");
using (FileStream fs = File.Create(jsonPath))
using (StreamWriter jsonStream = new StreamWriter(fs))
{
    var jsonSerializer = new Newtonsoft.Json.JsonSerializer();
    jsonSerializer.Serialize(jsonStream, people);
}

If I create a minimal Person class in order to be able to compile your code I get a json file that looks like this:

[{
        "FirstName": "Adam",
        "LastName": "Smith",
        "DateOfBirth": "1756-12-12T00:00:00",
        "Children": null
    }, {
        "FirstName": "Lisa",
        "LastName": "Simpson",
        "DateOfBirth": "1980-04-30T00:00:00",
        "Children": null
    }, {
        "FirstName": "Barney",
        "LastName": "Rubble",
        "DateOfBirth": "1962-07-14T00:00:00",
        "Children": [{
                "FirstName": "Bob",
                "LastName": "Rubble",
                "DateOfBirth": "1986-05-03T00:00:00",
                "Children": null
            }, {
                "FirstName": "Bamm-Bamm",
                "LastName": "Rubble",
                "DateOfBirth": "1984-03-15T00:00:00",
                "Children": null
            }
        ]
    }
]
Retired Ninja
  • 4,785
  • 3
  • 25
  • 35
  • Thank you so much! I'm going to try this immediately! – Craig Paulk Apr 17 '20 at 14:10
  • 1
    This was exactly what I needed. Now that I look at it, it makes sense because I see I can pass a Stream type to create a StreamWriter and FileStream inherits from Stream. – Craig Paulk Apr 17 '20 at 14:22
-1

You can use this JSONHelpers.

public static class JsonHelpers
{
    public static T CreateFromJsonStream<T>(this Stream stream)
    {
        JsonSerializer serializer = new JsonSerializer();
        T data;
        using (StreamReader streamReader = new StreamReader(stream))
        {
            data = (T)serializer.Deserialize(streamReader, typeof(T));
        }
        return data;
    }

    public static T CreateFromJsonString<T>(this String json)
    {
        T data;
        using (MemoryStream stream = new MemoryStream(System.Text.Encoding.Default.GetBytes(json)))
        {
            data = CreateFromJsonStream<T>(stream);
        }
        return data;
    }

    public static T CreateFromJsonFile<T>(this String fileName)
    {
        T data;
        using (FileStream fileStream = new FileStream(fileName, FileMode.Open))
        {
            data = CreateFromJsonStream<T>(fileStream);
        }
        return data;
    }
}

Please check out this LINK for a detailed explanation. You can use these extension methods to convert the stream to JSON string.

Nainesh Patel
  • 488
  • 2
  • 5
  • 19
  • 1
    Thank you, @Nainesh. I will look at these tomorrow to see if they may help. – Craig Paulk Apr 16 '20 at 03:18
  • 1
    https://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers – mjwills Apr 16 '20 at 03:28
  • Thank you so much. Now it makes sense. I am going to update my answer now. – Nainesh Patel Apr 16 '20 at 03:39
  • 1
    Sorry - this seems to be good for deserializing data from a JSON file, but I'm going in the opposite direction. I'm trying to create a JSON file, then serialize data into JSON format and write it to the file. Thank you for this though - I may be able to use this down the road. – Craig Paulk Apr 16 '20 at 14:46