DataTable в JSON

Недавно мне нужно было сериализовать данные в JSON. Где я сейчас, мы все еще на .Net 2.0, поэтому я не могу использовать сериализатор JSON в .Net 3.5. Я решил, что это должно было быть сделано раньше, поэтому я поискал в Интернете и нашел нашел как номер из разныепараметры. Некоторые из них зависят от дополнительной библиотеки, которую мне было бы трудно протолкнуть здесь. Другие требуют предварительного преобразования в List<Dictionary<>>, что кажется немного неудобным и ненужным. Другой рассматривал все значения как строку. По тем или иным причинам я не мог реально отстать ни от одного из них, поэтому решил выложить свой собственный, который опубликован ниже.

Как вы можете видеть из комментариев к //TODO, в некоторых местах он неполный. Этот код здесь уже находится в разработке, так что он «работает» в основном смысле. Места, где он неполный, - это места, где мы знаем, что наши производственные данные в настоящее время не попадут в него (нет временных интервалов или байтовых массивов в базе данных). Причина, по которой я публикую здесь, заключается в том, что я чувствую, что это может быть немного лучше, и мне бы хотелось помочь доработать и улучшить этот код. Любой ввод приветствуется.

Обратите внимание, что эта возможность встроена в .Net 3.5 и новее, и поэтому единственная причина использовать этот код сегодня - это если вы по-прежнему ограничены .Net 2.0. Даже тогда JSON.Net стал библиотекой goto для такого рода вещей.

public static class JSONHelper
{
    public static string FromDataTable(DataTable dt)
    {
        string rowDelimiter = "";

        StringBuilder result = new StringBuilder("[");
        foreach (DataRow row in dt.Rows)
        {
            result.Append(rowDelimiter);
            result.Append(FromDataRow(row));
            rowDelimiter = ",";
        }
        result.Append("]");

        return result.ToString();
    }

    public static string FromDataRow(DataRow row)
    {
        DataColumnCollection cols = row.Table.Columns;
        string colDelimiter = "";

        StringBuilder result = new StringBuilder("{");       
        for (int i = 0; i < cols.Count; i++)
        { // use index rather than foreach, so we can use the index for both the row and cols collection
            result.Append(colDelimiter).Append("\"")
                  .Append(cols[i].ColumnName).Append("\":")
                  .Append(JSONValueFromDataRowObject(row[i], cols[i].DataType));

            colDelimiter = ",";
        }
        result.Append("}");
        return result.ToString();
    }

    // possible types:
    // http://msdn.microsoft.com/en-us/library/system.data.datacolumn.datatype(VS.80).aspx
    private static Type[] numeric = new Type[] {typeof(byte), typeof(decimal), typeof(double), 
                                     typeof(Int16), typeof(Int32), typeof(SByte), typeof(Single),
                                     typeof(UInt16), typeof(UInt32), typeof(UInt64)};

    // I don't want to rebuild this value for every date cell in the table
    private static long EpochTicks = new DateTime(1970, 1, 1).Ticks;

    private static string JSONValueFromDataRowObject(object value, Type DataType)
    {
        // null
        if (value == DBNull.Value) return "null";

        // numeric
        if (Array.IndexOf(numeric, DataType) > -1)
            return value.ToString(); // TODO: eventually want to use a stricter format. Specifically: separate integral types from floating types and use the "R" (round-trip) format specifier

        // boolean
        if (DataType == typeof(bool))
            return ((bool)value) ? "true" : "false";

        // date -- see http://weblogs.asp.net/bleroy/archive/2008/01/18/dates-and-json.aspx
        if (DataType == typeof(DateTime))       
            return "\"\/Date(" + new TimeSpan(((DateTime)value).ToUniversalTime().Ticks - EpochTicks).TotalMilliseconds.ToString() + ")\/\"";

        // TODO: add Timespan support
        // TODO: add Byte[] support

        //TODO: this would be _much_ faster with a state machine
        //TODO: way to select between double or single quote literal encoding
        //TODO: account for database strings that may have single \r or \n line breaks
        // string/char  
        return "\"" + value.ToString().Replace(@"\", @"\\").Replace(Environment.NewLine, @"\n").Replace("\"", @"\""") + "\"";
    }
}

Обновлять:
Сейчас это устарело, но я хотел указать кое-что о том, как этот код обрабатывает даты. Формат, который я использовал, имел смысл в то время для точного обоснования URL-адреса. Однако это обоснование включает следующее:

To be perfectly honest, JSON Schema does solve the problem by making it possible to "subtype" a string as a date literal, but this is still work in progress and it will take time before any significant adoption is reached.

Что ж, время прошло. Сегодня можно просто использовать формат даты ISO 8601. Я не буду утруждать себя изменением кода, потому что на самом деле: это очень давно. Просто используйте JSON.Net.

Если бы об этом спросили сегодня, он бы попал в обмен на стек проверки кода. Я пометил, что его нужно переместить туда, но единственная причина, по которой он привлек мое внимание, - это то, что он только что получил золотой значок «Знаменитый вопрос». Было бы ужасно потерять это количество просмотров при миграции.

Joel Coehoorn 08.05.2012 18:18

Я думаю, что это было бы слишком старым для миграции. Он может жить здесь, если ты с этим согласен?

Kev 09.05.2012 02:48

Я не возражаю в любом случае, просто думаю о том, что лучше всего подходит. Я перевезла другие старые вещи.

Joel Coehoorn 09.05.2012 07:01

Отличный код. Очень полезно и просто.

Alex 17.05.2012 14:51

Почему это все еще набирает голоса? .Net 2 исполнилось 8 лет, и более поздние версии конвертируются в json из коробки. Нет веских причин больше нуждаться в этом. Кроме того, FWIW, теперь я знаю, что меня беспокоило с исходным кодом: я должен был запрашивать строку в качестве аргумента, передавшего мои функции (или в конструктор), и записывать свои строки json в этот Straem с любым взглядом, чтобы позволить asp Программисты .net передают поток Response.Output. Это должно улучшить производительность / масштабируемость сильно.

Joel Coehoorn 17.12.2012 18:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
19
5
30 976
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Нашел вот это: http://www.bramstein.com/projects/xsltjson/ Вы можете преобразовать свою таблицу данных в xml и использовать таблицу стилей xslt для преобразования xml в json.

Это скорее обходной путь, чем реальное решение.

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

Joel Coehoorn 17.01.2009 00:21
Ответ принят как подходящий

Помогло бы вам убедить начальство установить библиотеку, если это Microsoft Расширения AJAX для .NET 2.0?

В них включен System.Web.Script.Serialization.JavascriptSerializer, который используется в шаге 4 последняя ссылка в вашем сообщении.

Есть ли способ сделать это без установки дополнительных библиотек?

Steam 05.02.2014 00:28

Привет, дружище, все это здесь, в сообщении блога Рика Сериализация DataTable с использованием Json.NET. Он подробно объясняет, как это можно сделать, используя Json.NET из Джеймс Ньютон Кинг.

Вы не должны публиковать ответы, на которые есть ссылка

Evan Carroll 24.12.2017 08:53

Другие вопросы по теме