Преобразование строки JSON в CSV и CSV в JSON в c#

#c# #json #csv #asp.net-core #asp.net-web-api

Вопрос:

Я работаю с файлами JSON / CSV в моем asp.net проект веб-API и попробовал с помощью CSVHelper и ServiceStack.Текстовые библиотеки, но не смог заставить их работать.

Файл JSON, содержащий массив, является динамическим и может содержать любое количество полей

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

пример текста файла

 [{"COLUMN1":"a","COLUMN2":"b","COLUMN3":"c","COLUMN4":"d","COLUMN5":"e"},
 {"COLUMN1":"a","COLUMN2":"b","COLUMN3":"c","COLUMN4":"d","COLUMN5":"e"}]
 

JSON в CSV

 public static string jsonStringToCSV(string content)
{
    var jsonContent = (JArray)JsonConvert.DeserializeObject(content);

    var csv = ServiceStack.Text.CsvSerializer.SerializeToCsv(jsonContent);
    return csv;
}
 

Это не приводит к получению данных CSV

введите описание изображения здесь

Затем некоторые файлы имеют тип разделителя с запятой или табуляцией, и я хочу использовать CSVHelper для динамического преобразования строки CSV в IEnumerable

 public static IEnumerable StringToList(string data, string delimiter, bool HasHeader)
{
    using (var csv = new CsvReader(new StringReader(data)))
    {
         csv.Configuration.SkipEmptyRecords = true;
         csv.Configuration.HasHeaderRecord = HasHeader;
         csv.Configuration.Delimiter = delimiter;

         var records = csv.GetRecords();
         return records;
     }
}
 

Комментарии:

1. Не могли бы вы предоставить нам, пожалуйста, сообщение об ошибке или вывод

2. @Eminem Пожалуйста, посмотрите скриншот excel.

3. Я запрашиваю вывод, который он ДАЕТ. Не то, что вы ожидаете от этого

4. Да, то же самое, скриншот показывает, что он дает не так, как я ожидал.

5. Mybad. Я думал, что это фактические значения

Ответ №1:

Я смог решить эту проблему путем десериализации объекта в datatable с помощью Json.net , поэтому хочу опубликовать свой собственный ответ, но не буду отмечать его как принятый, если у кого-нибудь есть лучший способ сделать это.

Для преобразования строки JSON в DataTable

 public static DataTable jsonStringToTable(string jsonContent)
        {
            DataTable dt = JsonConvert.DeserializeObject<DataTable>(jsonContent);
            return dt;
        }
 

Чтобы создать строку CSV

 public static string jsonToCSV(string jsonContent, string delimiter)
        {
            StringWriter csvString = new StringWriter();
            using (var csv = new CsvWriter(csvString))
            {
                csv.Configuration.SkipEmptyRecords = true;
                csv.Configuration.WillThrowOnMissingField = false;
                csv.Configuration.Delimiter = delimiter;

                using (var dt = jsonStringToTable(jsonContent))
                {
                    foreach (DataColumn column in dt.Columns)
                    {
                        csv.WriteField(column.ColumnName);
                    }
                    csv.NextRecord();

                    foreach (DataRow row in dt.Rows)
                    {
                        for (var i = 0; i < dt.Columns.Count; i  )
                        {
                            csv.WriteField(row[i]);
                        }
                        csv.NextRecord();
                    }
                }
            }
            return csvString.ToString();
        }
 

Окончательное использование в веб-API

 string csv = jsonToCSV(content, ",");

                HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
                result.Content = new StringContent(csv);
                result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
                result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "export.csv" };
                return resu<
 

Комментарии:

1. Именно то, чего я пытался достичь. Отлично работает!

2. Отлично ли это работает? Мой jsonStringToTable разбился из-за форматирования в newtonsoft.

3. Когда я ищу в библиотеке NuGet Json. NET Я возвращаю Newtonsoft. Json в окне результатов. Я думаю, это то же самое. Он уже установлен в моем проекте, но CSVWriter, похоже, отсутствует. Проект использует . NET v4.6.2 Есть идеи, как заставить его работать?

4. CSVWriter доступен в другом пакете под названием CSVHelper — github.com/JoshClose/CsvHelper вы можете установить > Установить-Пакет CSVHelper

5. что вы делаете, когда у вас есть объект Json в качестве поля? Десериализация в DataTable выдаст ошибку

Ответ №2:

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

Cinchoo ETL упрощает преобразование JSON в csv с помощью нескольких строк кода

 using (var r = new ChoJSONReader("sample.json"))
{
    using (var w = new ChoCSVWriter("sample.csv").WithFirstLineHeader())
    {
        w.Write(r);
    }
}
 

Для получения дополнительной информации / источника перейдите по ссылке https://github.com/Cinchoo/ChoETL

Пакет Nuget:

.NET Framework:

       Install-Package ChoETL.JSON
 

.NET Core:

       Install-Package ChoETL.JSON.NETStandard
 

Пример скрипки: https://dotnetfiddle.net/T3u4W2

Полное раскрытие: я автор этой библиотеки.

Комментарии:

1. понятно. К вашему сведению, это библиотека с открытым исходным кодом, показывающая, как решить проблему с ее помощью. Не более того.

2. Я понимаю. Я просто говорю, как это воспринимается сообществом. Просто укажите ваше отношение к библиотеке, и все должно быть в порядке.

3. Я установил ваш Install-Package ChoETL , а затем пытаюсь добавить его пространство имен. Но система выдает мне ошибку отсутствия ссылки . Я также очистил решение, но все напрасно. Не могли бы вы помочь!! @RajN

4. Ваш проект .net framework или .net core? Если .net core использует стандартный пакет ChoETL.JSON.net. Если .net framework, используйте ChoETL.JSON

5. Эта библиотека превосходна. Он распутывает даже вложенные уровни json в csv, захватывая все данные.

Ответ №3:

Недавно была такая же проблема, и я считаю, что есть немного более элегантное решение с использованием системы.Dynamic.ExpandoObject и CSVHelper. Это меньше кода, и, надеюсь, производительность аналогична или лучше по сравнению с таблицей данных.

     public static string JsonToCsv(string jsonContent, string delimiter)
    {
        var expandos = JsonConvert.DeserializeObject<ExpandoObject[]>(jsonContent);

        using (var writer = new StringWriter())
        {
            using (var csv = new CsvWriter(writer))
            {
                csv.Configuration.Delimiter = delimiter;

                csv.WriteRecords(expandos as IEnumerable<dynamic>);
            }

            return writer.ToString();
        }
    }
 

Комментарии:

1. Я нашел это решение лучшим из всех. 🙂

2. Не удается заставить это работать, если в некоторых записях отсутствуют некоторые значения

Ответ №4:

Этот код подходит для меня:

3 функции (проверка, анализ и aux)

     private bool IsValidJson(string strInput)
    {
        try 
        { 
            if (string.IsNullOrWhiteSpace(strInput)) { return false; }
        
            strInput = strInput.Trim();

            if ((strInput.StartsWith("{") amp;amp; strInput.EndsWith("}")) || (strInput.StartsWith("[") amp;amp; strInput.EndsWith("]"))) 
            {
                try
                {
                    _ = JToken.Parse(strInput);

                    return true;
                }
                catch
                {
                    return false;
                }
            }

            return false;
        }
        catch { throw; }
    }

    private string ParseJsonToCsv(string json)
    {
        try
        {
            XmlNode xml = JsonConvert.DeserializeXmlNode("{records:{record:"   json   "}}");

            XmlDocument xmldoc = new XmlDocument(); xmldoc.LoadXml(xml.InnerXml);

            DataSet dataSet = new DataSet(); dataSet.ReadXml(new XmlNodeReader(xmldoc));

            string csv = DTableToCsv(dataSet.Tables[0], ",");

            return csv;
        }
        catch { throw; }
    }

    private string DTableToCsv(DataTable table, string delimator)
    {
        try 
        { 
            var result = new StringBuilder();

            for (int i = 0; i < table.Columns.Count; i  )
            {
                result.Append(table.Columns[i].ColumnName);
                result.Append(i == table.Columns.Count - 1 ? "n" : delimator);
            }

            foreach (DataRow row in table.Rows)
                for (int i = 0; i < table.Columns.Count; i  )
                {
                    result.Append(row[i].ToString());
                    result.Append(i == table.Columns.Count - 1 ? "n" : delimator);
                }

            return result.ToString().TrimEnd(new char[] { 'r', 'n' });
        }
        catch { throw; }
    }
 

Ответ №5:

 public void Convert2Json() 
        { 
            try 
            { 
                if (FileUpload1.PostedFile.FileName != string.Empty) 
                { 
                    string[] FileExt = FileUpload1.FileName.Split('.'); 
                    string FileEx = FileExt[FileExt.Length - 1]; 
                    if (FileEx.ToLower() == "csv") 
                    { 
                        string SourcePath = Server.MapPath("Resources//"   FileUpload1.FileName); 
                        FileUpload1.SaveAs(SourcePath); 
                        string Destpath = (Server.MapPath("Resources//"   FileExt[0]   ".json")); 

                        StreamWriter sw = new StreamWriter(Destpath); 
                        var csv = new List<string[]>(); 
                        var lines = System.IO.File.ReadAllLines(SourcePath); 
                        foreach (string line in lines) 
                            csv.Add(line.Split(',')); 
                        string json = new 
                            System.Web.Script.Serialization.JavaScriptSerializer().Serialize(csv); 
                        sw.Write(json); 
                        sw.Close(); 
                        TextBox1.Text = Destpath; 
                        MessageBox.Show("File is converted to json."); 
                    } 
                    else 
                    { 
                        MessageBox.Show("Invalid File"); 
                    } 

                } 
                else 
                { 
                    MessageBox.Show("File Not Found."); 
                } 
            } 
            catch (Exception ex) 
            { 
                MessageBox.Show(ex.Message); 
            } 
        }
 

Комментарии:

1. Вы используете строку. Разделение (‘,’), что не очень хорошая идея. Лучше использовать программу чтения csv.

Ответ №6:

 using System.Globalization;

using (var csv = new CsvWriter(csvString, CultureInfo.CurrentCulture)) {
  ...
}