Newtonsoft Json Converter преобразует int в строку

Я читаю данные из базы данных Oracle в таблицу данных, конвертирую их в JSON, и кажется, что он преобразует int, который равен 1335 в строке таблицы данных, в «1335.0», что вызывает проблему при десериализации.

Столбцы определены в базе данных как:

REQUEST_ID      NUMBER(20,0)

(Частичный) запрос выглядит так:

SELECT req.REQUEST_ID AS \"uniqueId\", 

Я вызываю API, который возвращает результат этого запроса в таблицу данных C#:

DataTable dt = ODCException.GetError();

Когда я проверяю строки «dt», я вижу, что uniqueId равен 1335, 1336 и т. д.

Я также определил класс для хранения каждого отдельного объекта как:

public class jsonObject
{
    public int uniqueId { get; set; }
    ....
}

Когда я сериализую "dt":

string JSONresult = JsonConvert.SerializeObject(dt);

и проверьте JSONresult, который я вижу:

[{"uniqueId":1335.0,...}, {"uniqueId":1336.0,...}]

И позже, когда я пытаюсь десериализовать:

List<jsonObject> loErrorData = JsonConvert.DeserializeObject<IEnumerable<jsonObject>>(JSONresult).ToList();

Я получил:

{"Input string '1335.0' is not a valid integer. Path '[0].uniqueId', line 1, position 19."}

Мне нужно иметь возможность получить результат, в котором "uniqueId" имеет значение int, а не строку.

Обновлять

Мне удалось решить проблему следующим образом. Несмотря на то, что рассматриваемый столбец объявлен в базе данных как NUMBER (28,0), т. Е. Без десятичной точки, я продолжал получать «1335.0» вместо 1335 для столбца «uniqueId».

Так:

public static DataTable GetTCErrors()
{
    DataSet ds = oRespository.GetErrors();  // Get data from DB
    DataTable dt2 = new DataTable();

    if (ds.Tables.Count > 0)
    {
        DataTable dt = new DataTable();
        dt = ds.Tables[0];
        dt2.Columns.Add("uniqueId", typeof(Int32));
        dt2.Load(dt.CreateDataReader(), LoadOption.OverwriteChanges);
    }
    return dt2;
}

Теперь, когда я использую следующее, я получаю 1335, 1336,... как значения uniqueId в JSONresult:

DataTable dt = ODCException.GetTCErrors();
string JSONresult = JsonConvert.SerializeObject(dt);

Это работает, если вы удалите десятичную дробь?

mxmissile 20.04.2023 18:32
JsonConvert не будет сериализовать int с десятичной точкой. Пожалуйста, покажите скрипку, демонстрирующую проблему. Возможно, dt на самом деле DataTable, а не jsonObject?
Charlieface 20.04.2023 18:37

Что такое dt? Какой это тип? DataTable? Покажите, пожалуйста, как вы получаете данные из базы данных?

Guru Stron 20.04.2023 18:40

@mxmissile Я не могу удалить десятичную дробь, это то, что возвращает JsonConvert.

NoBullMan 20.04.2023 19:17

@ gunr2171 Я создал скрипку, но не могу ее воспроизвести! dotnetfiddle.net/OgG6py, Не знаю, где искать проблему. Я тоже обновил вопрос.

NoBullMan 20.04.2023 19:47

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

NoBullMan 20.04.2023 20:13

@Charlieface ответил на мое намерение удалить десятичную дробь, вот ваш ответ.

mxmissile 20.04.2023 20:29

Вот ваша реплика dotnetfiddle.net/9RbgPb Я проголосовал за повторное открытие. Решение в основном состоит в том, чтобы изменить запрос, чтобы он читался SELECT CAST(req.REQUEST_ID AS int) AS uniqueId

Charlieface 20.04.2023 20:57

Не уверен, что сказать, правда. Я показал столбец базы данных, объявленный как (NUMBER), набор данных, полученный в результате запроса, показывает значения int для «uniqueId» как 1335 и 1336. И сразу после JsconConvert.Serialize я получаю «1335.0» и «1336.0». Как вы видите в скрипке, которую я опубликовал, я не могу воспроизвести ее в скрипке, что еще больше расстраивает. Только не знаю, где искать проблему.

NoBullMan 20.04.2023 20:59

Моя ссылка на репродукцию показывает, что столбец с типом decimal вызовет эту ошибку. Если столбец хранится в базе данных как NUMBER, то он будет преобразован в decimal, а не int на стороне C#, поэтому вам нужно выполнить приведение.

Charlieface 20.04.2023 21:05

@Charlieface, спасибо. Кастинг в запросе Oracle не помог, та же ошибка. Кроме того, в Oracle этот столбец уже NUMBER (28,0), без десятичных знаков. Ваша рабочий пример указывает на то, что десериализация в список объектов, где «uniqueId» определяется как int, вызывает ошибку. Я не понимаю, как значение столбца с данными, которое является int (1335), преобразуется в «1335.0» после вызова JsonConvert.Serialize.

NoBullMan 20.04.2023 21:23

Я нашел обходной путь, который решил проблему. Я добавил в часть вопроса «Обновить».

NoBullMan 20.04.2023 21:31
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
13
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Тот факт, что столбец объявлен NUMERIC(28,0), не преобразует его в int на стороне C#. Только если это INTEGER, то так и будет.

Так что вы можете просто использовать его в Oracle

SELECT CAST(req.REQUEST_ID AS INTEGER) AS "uniqueId",

Сказав это, ваш другой вариант - использовать его на стороне С#. Вы уже предоставили один из способов сделать это, сначала добавив столбец с typeof(int) в DataTable.

Но, честно говоря, если вы создаете объектную модель, вам следует просто отказаться от DataTable и напрямую использовать ридер.

public static List<jsonObject> GetTCErrors()
{
    var list = new List<jsonObject>();
    using var conn = new OracleConnection(YourConnString);
    using var comm = new OracleCommand(YourQuery, conn);
    // parameters here
    conn.Open();
    using var reader = comm.ExecuteReader();
    while (reader.Read())
    {
        list.Add(new jsonObject
        {
            uniqueId = (int)(decimal)reader["uniqueId"],  // notice the double-cast
        }
    }
    return list;
}

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

Вы абсолютно правы. Я должен был сделать это в первую очередь и избавить себя от большого горя. Вывод всего этого идет к брокеру Kafka, и они требуют, чтобы данные были в формате JSON. Когда я делаю это в Oracle 19c+, я просто использую json_object, и все готово. Именно с Oracle до 19c мне приходится выполнять это преобразование JSON вручную.

NoBullMan 21.04.2023 01:45

Я использовал ваш метод использования считывателя вместо набора данных. Пометил ваш ответ как ответ. Спасибо за помощь.

NoBullMan 21.04.2023 05:19

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