Переход из Newtonsoft.JsonSystem.Text.Json
В этой статье описывается миграция из Newtonsoft.Json в System.Text.Json.
Пространство имен System.Text.Json
предоставляет функциональные возможности для сериализации в нотацию объектов JavaScript (JSON) и десериализации объектов из этой нотации. Библиотека System.Text.Json
включается в среду выполнения для .NET Core 3.1 и более поздних версий. Для других целевых платформ установите пакет NuGet System.Text.Json. Пакет поддерживает:
- .NET Standard 2.0 и более поздних версий
- .NET Framework 4.6.2 и более поздние версии
- .NET Core 2.0, 2.1 и 2.2
Совет
Вы можете использовать помощь ИИ для миграции с Newtonsoft.Json
помощью GitHub Copilot.
System.Text.Json
основное внимание уделяет требованиям, предъявляемым к производительности, безопасности и стандартам. У него есть некоторые ключевые отличия в поведении по умолчанию, и он не стремится к равенству функций с Newtonsoft.Json
. В некоторых сценариях в настоящее время нет встроенных функциональных System.Text.Json
возможностей, но существуют рекомендуемые обходные пути. В других сценариях обходные пути нецелесообразны.
Команда System.Text.Json
инвестирует в добавление функций, которые чаще всего запрашиваются. Если приложение зависит от отсутствующего компонента, рассмотрите возможность отправки проблемы в репозитории dotnet/runtime GitHub, чтобы узнать, может ли быть добавлена поддержка вашего сценария.
Большая часть этой статьи посвящена использованию API JsonSerializer, но также содержит рекомендации по использованию JsonDocument (который представляет модель DOM), Utf8JsonReader и типов Utf8JsonWriter.
В Visual Basic нельзя использовать Utf8JsonReader, что также означает, что вы не можете писать пользовательские преобразователи. Большинство обходных решений, представленных здесь, требуют написания пользовательских преобразователей. Вы можете написать пользовательский преобразователь в C# и зарегистрировать его в проекте Visual Basic. Дополнительные сведения см. в статье о поддержке Visual Basic.
Таблица различий
В следующей таблице перечислены функции Newtonsoft.Json
и эквиваленты System.Text.Json
. Эквиваленты делятся на следующие категории:
- ✔️ Поддерживается встроенными функциями. Для получения аналогичного поведения
System.Text.Json
может потребоваться использование атрибута или глобального параметра. - ⚠️ Не поддерживается, но возможно обходное решение. Обходные пути — это пользовательские преобразователи, которые могут не обеспечить полную четность с
Newtonsoft.Json
функциональными возможностями. Для некоторых случаев приведены примеры кода. Если вы используете эти функцииNewtonsoft.Json
, для миграции потребуется внести изменения в объектные модели .NET или другие части кода. - ❌ Не поддерживается и обходной путь не является практическим или возможным. Если вы используете эти функции
Newtonsoft.Json
, миграция будет невозможна без существенных изменений.
Функция в Newtonsoft.Json | Эквивалент System.Text.Json |
---|---|
Десериализация без учета регистра по умолчанию | ✔️ Глобальный параметр PropertyNameCaseInsensitive |
Имена свойств в "верблюжьем" стиле | ✔️ Глобальный параметр PropertyNamingPolicy |
Имена свойств змеиного регистра | ✔️ Политика именования регистра змеи |
Минимальное экранирование символов | ✔️ Строгое экранирование символов, возможность настройки |
Глобальный параметр NullValueHandling.Ignore |
✔️ Глобальный параметр DefaultIgnoreCondition |
Возможность комментариев | ✔️ Глобальный параметр ReadCommentHandling |
Возможность конечных запятых | ✔️ Глобальный параметр AllowTrailingCommas |
Регистрация пользовательского преобразователя | ✔️ Очередность применения различается |
Максимальная глубина по умолчанию 64, настраиваемая | ✔️ Максимальная глубина по умолчанию —64, настраиваемая |
Глобальный параметр PreserveReferencesHandling |
✔️ Глобальный параметр ReferenceHandling |
Сериализация или десериализация чисел в кавычках | ✔️ Глобальный параметр NumberHandling, атрибут [JsonNumberHandling] |
Десериализация в неизменяемые классы и структуры | ✔️ JsonConstructor, записи C# 9 |
Поддержка полей | ✔️ Глобальный параметр IncludeFields, атрибут [JsonInclude] |
Глобальный параметр DefaultValueHandling |
✔️ Глобальный параметр DefaultIgnoreCondition |
УстановкаNullValueHandling для атрибута [JsonProperty] |
✔️ Атрибут JsonIgnore |
УстановкаDefaultValueHandling для атрибута [JsonProperty] |
✔️ Атрибут JsonIgnore |
Десериализация Dictionary с ключом, не являющимся строкой |
✔️ Поддерживается |
Поддержка методов задания и методов получения свойств, которые не являются общими | ✔️ Атрибут JsonInclude |
Атрибут [JsonConstructor] |
✔️ Атрибут [JsonConstructor] |
Глобальный параметр ReferenceLoopHandling |
✔️ Глобальный параметр ReferenceHandling |
Обратные вызовы | ✔️ Обратные вызовы |
NaN, Бесконечность, -Бесконечность | ✔️ Поддерживается |
Установка Required для атрибута [JsonProperty] |
✔️ Атрибут [JsonRequired] и обязательный модификатор C# |
DefaultContractResolver для игнорирования свойств |
✔️ Класс DefaultJsonTypeInfoResolver |
Полиморфная сериализация | ✔️ Атрибут [JsonDerivedType] |
Полиморфная десериализация | ✔️ Тип дискриминационный для атрибута [JsonDerivedType] |
Десериализация значения перечисления строки | ✔️ Десериализация строковых значений перечисления |
Глобальный параметр MissingMemberHandling |
✔️ Обработка отсутствующих элементов |
Заполнение свойств без наборов | ✔️ Заполнение свойств без наборов |
Глобальный параметр ObjectCreationHandling |
✔️ Повторное использование, а не замена свойств |
Поддержка широкого спектра типов | ⚠️ Для некоторых типов требуются пользовательские преобразователи |
Десериализация выводимого типа в свойства object |
⚠️ Не поддерживается, обходное решение, пример |
Десериализация литерала JSON null в типы значений, не допускающие значения NULL |
⚠️ Не поддерживается, обходное решение, пример |
Параметры DateTimeZoneHandling , DateFormatString |
⚠️ Не поддерживается, обходное решение, пример |
JsonConvert.PopulateObject Метод |
⚠️ Не поддерживается, обходной путь |
Поддержка атрибутов System.Runtime.Serialization |
⚠️ Не поддерживается, обходное решение, пример |
JsonObjectAttribute |
⚠️ Не поддерживается, обходной путь |
Возможность имен свойств без кавычек | ❌Не поддерживается проектом |
Возможность одиночных кавычек вокруг строковых значений | ❌Не поддерживается проектом |
Возможность нестроковых значений JSON для строковых свойств | ❌Не поддерживается проектом |
Глобальный параметр TypeNameHandling.All |
❌Не поддерживается проектом |
JsonPath Поддержка запросов |
❌Не поддерживаются |
Настраиваемые ограничения | ❌Не поддерживаются |
Функция в Newtonsoft.Json | Эквивалент System.Text.Json |
---|---|
Десериализация без учета регистра по умолчанию | ✔️ Глобальный параметр PropertyNameCaseInsensitive |
Имена свойств в "верблюжьем" стиле | ✔️ Глобальный параметр PropertyNamingPolicy |
Минимальное экранирование символов | ✔️ Строгое экранирование символов, возможность настройки |
Глобальный параметр NullValueHandling.Ignore |
✔️ Глобальный параметр DefaultIgnoreCondition |
Возможность комментариев | ✔️ Глобальный параметр ReadCommentHandling |
Возможность конечных запятых | ✔️ Глобальный параметр AllowTrailingCommas |
Регистрация пользовательского преобразователя | ✔️ Очередность применения различается |
Максимальная глубина по умолчанию 64, настраиваемая | ✔️ Максимальная глубина по умолчанию —64, настраиваемая |
Глобальный параметр PreserveReferencesHandling |
✔️ Глобальный параметр ReferenceHandling |
Сериализация или десериализация чисел в кавычках | ✔️ Глобальный параметр NumberHandling, атрибут [JsonNumberHandling] |
Десериализация в неизменяемые классы и структуры | ✔️ JsonConstructor, записи C# 9 |
Поддержка полей | ✔️ Глобальный параметр IncludeFields, атрибут [JsonInclude] |
Глобальный параметр DefaultValueHandling |
✔️ Глобальный параметр DefaultIgnoreCondition |
УстановкаNullValueHandling для атрибута [JsonProperty] |
✔️ Атрибут JsonIgnore |
УстановкаDefaultValueHandling для атрибута [JsonProperty] |
✔️ Атрибут JsonIgnore |
Десериализация Dictionary с ключом, не являющимся строкой |
✔️ Поддерживается |
Поддержка методов задания и методов получения свойств, которые не являются общими | ✔️ Атрибут JsonInclude |
Атрибут [JsonConstructor] |
✔️ Атрибут [JsonConstructor] |
Глобальный параметр ReferenceLoopHandling |
✔️ Глобальный параметр ReferenceHandling |
Обратные вызовы | ✔️ Обратные вызовы |
NaN, Бесконечность, -Бесконечность | ✔️ Поддерживается |
Установка Required для атрибута [JsonProperty] |
✔️ Атрибут [JsonRequired] и обязательный модификатор C# |
DefaultContractResolver для игнорирования свойств |
✔️ Класс DefaultJsonTypeInfoResolver |
Полиморфная сериализация | ✔️ Атрибут [JsonDerivedType] |
Полиморфная десериализация | ✔️ Тип дискриминационный для атрибута [JsonDerivedType] |
Десериализация значения перечисления строки | ✔️ Десериализация строковых значений перечисления |
Поддержка широкого спектра типов | ⚠️ Для некоторых типов требуются пользовательские преобразователи |
Десериализация выводимого типа в свойства object |
⚠️ Не поддерживается, обходное решение, пример |
Десериализация литерала JSON null в типы значений, не допускающие значения NULL |
⚠️ Не поддерживается, обходное решение, пример |
Параметры DateTimeZoneHandling , DateFormatString |
⚠️ Не поддерживается, обходное решение, пример |
JsonConvert.PopulateObject Метод |
⚠️ Не поддерживается, обходной путь |
Глобальный параметр ObjectCreationHandling |
⚠️ Не поддерживается, обходной путь |
Добавление в коллекции без методов задания | ⚠️ Не поддерживается, обходной путь |
Имена свойств змеиного регистра | ⚠️ Не поддерживается, обходной путь |
Поддержка атрибутов System.Runtime.Serialization |
⚠️ Не поддерживается, обходное решение, пример |
Глобальный параметр MissingMemberHandling |
⚠️ Не поддерживается, обходное решение, пример |
JsonObjectAttribute |
⚠️ Не поддерживается, обходной путь |
Возможность имен свойств без кавычек | ❌Не поддерживается проектом |
Возможность одиночных кавычек вокруг строковых значений | ❌Не поддерживается проектом |
Возможность нестроковых значений JSON для строковых свойств | ❌Не поддерживается проектом |
Глобальный параметр TypeNameHandling.All |
❌Не поддерживается проектом |
JsonPath Поддержка запросов |
❌Не поддерживаются |
Настраиваемые ограничения | ❌Не поддерживаются |
Функция в Newtonsoft.Json | Эквивалент System.Text.Json |
---|---|
Десериализация без учета регистра по умолчанию | ✔️ Глобальный параметр PropertyNameCaseInsensitive |
Имена свойств в "верблюжьем" стиле | ✔️ Глобальный параметр PropertyNamingPolicy |
Минимальное экранирование символов | ✔️ Строгое экранирование символов, возможность настройки |
Глобальный параметр NullValueHandling.Ignore |
✔️ Глобальный параметр DefaultIgnoreCondition |
Возможность комментариев | ✔️ Глобальный параметр ReadCommentHandling |
Возможность конечных запятых | ✔️ Глобальный параметр AllowTrailingCommas |
Регистрация пользовательского преобразователя | ✔️ Очередность применения различается |
Максимальная глубина по умолчанию 64, настраиваемая | ✔️ Максимальная глубина по умолчанию —64, настраиваемая |
Глобальный параметр PreserveReferencesHandling |
✔️ Глобальный параметр ReferenceHandling |
Сериализация или десериализация чисел в кавычках | ✔️ Глобальный параметр NumberHandling, атрибут [JsonNumberHandling] |
Десериализация в неизменяемые классы и структуры | ✔️ JsonConstructor, записи C# 9 |
Поддержка полей | ✔️ Глобальный параметр IncludeFields, атрибут [JsonInclude] |
Глобальный параметр DefaultValueHandling |
✔️ Глобальный параметр DefaultIgnoreCondition |
УстановкаNullValueHandling для атрибута [JsonProperty] |
✔️ Атрибут JsonIgnore |
УстановкаDefaultValueHandling для атрибута [JsonProperty] |
✔️ Атрибут JsonIgnore |
Десериализация Dictionary с ключом, не являющимся строкой |
✔️ Поддерживается |
Поддержка методов задания и методов получения свойств, которые не являются общими | ✔️ Атрибут JsonInclude |
Атрибут [JsonConstructor] |
✔️ Атрибут [JsonConstructor] |
Глобальный параметр ReferenceLoopHandling |
✔️ Глобальный параметр ReferenceHandling |
Обратные вызовы | ✔️ Обратные вызовы |
NaN, Бесконечность, -Бесконечность | ✔️ Поддерживается |
Десериализация значения перечисления строки | ✔️ Десериализация строковых значений перечисления |
Поддержка широкого спектра типов | ⚠️ Для некоторых типов требуются пользовательские преобразователи |
Полиморфная сериализация | ⚠️ Не поддерживается, обходное решение, пример |
Полиморфная десериализация | ⚠️ Не поддерживается, обходное решение, пример |
Десериализация выводимого типа в свойства object |
⚠️ Не поддерживается, обходное решение, пример |
Десериализация литерала JSON null в типы значений, не допускающие значения NULL |
⚠️ Не поддерживается, обходное решение, пример |
Установка Required для атрибута [JsonProperty] |
⚠️ Не поддерживается, обходное решение, пример |
DefaultContractResolver для игнорирования свойств |
⚠️ Не поддерживается, обходное решение, пример |
Параметры DateTimeZoneHandling , DateFormatString |
⚠️ Не поддерживается, обходное решение, пример |
JsonConvert.PopulateObject Метод |
⚠️ Не поддерживается, обходной путь |
Глобальный параметр ObjectCreationHandling |
⚠️ Не поддерживается, обходной путь |
Добавление в коллекции без методов задания | ⚠️ Не поддерживается, обходной путь |
Имена свойств змеиного регистра | ⚠️ Не поддерживается, обходной путь |
JsonObjectAttribute |
⚠️ Не поддерживается, обходной путь |
Поддержка атрибутов System.Runtime.Serialization |
❌Не поддерживаются |
Глобальный параметр MissingMemberHandling |
❌Не поддерживаются |
Возможность имен свойств без кавычек | ❌Не поддерживается проектом |
Возможность одиночных кавычек вокруг строковых значений | ❌Не поддерживается проектом |
Возможность нестроковых значений JSON для строковых свойств | ❌Не поддерживается проектом |
Глобальный параметр TypeNameHandling.All |
❌Не поддерживается проектом |
JsonPath Поддержка запросов |
❌Не поддерживаются |
Настраиваемые ограничения | ❌Не поддерживаются |
Это неполный список функций Newtonsoft.Json
. В список входят многие сценарии, которые были запрошены в проблемах GitHub или записях StackOverflow. Если вы реализуете обходной путь для одного из перечисленных здесь сценариев, для которого в настоящее время нет примера кода, и если вы хотите поделиться своим решением, нажмите Эта страница в разделе Отзывы (в нижней части этой страницы). Это позволит создать проблему в репозитории GitHub в этой документации и указать ее в разделе Отзывы на этой странице.
Различия в поведении по умолчанию
System.Text.Json по умолчанию является строгим и избегает двусмысленностей со стороны вызывающего объекта, подчеркивая детерминированное поведение. Библиотека преднамеренно разработана таким образом для повышения производительности и безопасности. Newtonsoft.Json
по умолчанию является гибким. Это фундаментальное различие в проектировании обуславливает многие из следующих различий в поведении по умолчанию.
Десериализация без учета регистра
Во время десериализации Newtonsoft.Json
выполняет сопоставление имени свойства без учета регистра по умолчанию. System.Text.Json по умолчанию учитывает регистр, что обеспечивает более высокую производительность, так как соответствие является точным. Сведения о том, как выполнять сопоставление без учета регистра, см. в разделе Сопоставление свойств без учета регистра.
Если вы используете System.Text.Json
косвенно с помощью ASP.NET Core, вам не нужно ничего делать для получения поведения, аналогичного Newtonsoft.Json
. ASP.NET Core задает параметры для имен свойств верблюда и не учитывает регистр при использовании System.Text.Json
.
ASP.NET Core также по умолчанию позволяет десериализовать заключенные в кавычки числа.
Минимальное экранирование символов
Во время сериализации Newtonsoft.Json
обеспечивает относительную свободу, разрешая символы без экранирования. То есть он не заменяет их на \uxxxx
, где xxxx
является кодовой точкой символа. Когда он использует экранирование, он выдает \
перед символом (например, "
преобразуется в \"
). System.Text.Json по умолчанию экранирует больше символов, чтобы обеспечить глубокую защиту от межсайтового скриптинга (XSS) или атак с раскрытием информации и делает это с помощью последовательности из шести символов. System.Text.Json
экранирует все символы, отличные от ASCII, по умолчанию, поэтому вам не нужно ничего делать, если вы используете StringEscapeHandling.EscapeNonAscii
в Newtonsoft.Json
. System.Text.Json
также по умолчанию экранирует символы, учитывающие HTML. Сведения о том, как переопределить поведение System.Text.Json
по умолчанию, см. в разделе Настройка кодировки символов.
Комментарии
Во время десериализации Newtonsoft.Json
по умолчанию игнорирует комментарии в JSON. System.Text.Json по умолчанию выдает исключения для комментариев, так как спецификация RFC 8259 не включает их. Сведения о том, как разрешить комментарии, см. в разделе Возможность комментариев и конечных запятых.
Конечные запятые
Во время десериализации Newtonsoft.Json
по умолчанию игнорирует конечные запятые. Он также игнорирует несколько конечных запятых (например, [{"Color":"Red"},{"Color":"Green"},,]
). System.Text.Json по умолчанию выдает исключения для конечных запятых, так как спецификация RFC 8259 не разрешает их. Сведения о том, как заставить System.Text.Json
их принять, см. в разделе Возможность комментариев и конечных запятых. Невозможно разрешить несколько конечных запятых.
Очередность регистрации преобразователей
Очередность регистрации Newtonsoft.Json
для пользовательских преобразователей выглядит следующим образом.
- Атрибут для свойства
- Атрибут для типа
- Коллекция преобразователей
Этот порядок означает, что пользовательский преобразователь в коллекции Converters
переопределяется преобразователем, зарегистрированным путем применения атрибута на уровне типа. Обе эти регистрации переопределяются атрибутом на уровне свойства.
Очередность регистрации System.Text.Json для пользовательских преобразователей выглядит иначе:
- Атрибут для свойства
- Коллекция Converters
- Атрибут для типа
Разница заключается в том, что пользовательский преобразователь в коллекции Converters
переопределяет атрибут на уровне типа. Цель этой очередности заключается в том, чтобы изменения во время выполнения переопределяли варианты во время разработки. Изменить очередность невозможно.
Дополнительные сведения о регистрации пользовательских преобразователей см. в разделе Регистрация пользовательского преобразователя.
Максимальная глубина
Последняя версия Newtonsoft.Json
имеет максимальный предел глубины 64 по умолчанию. System.Text.Json также имеет ограничение по умолчанию 64 и настраивается по параметру JsonSerializerOptions.MaxDepth.
Если вы используете System.Text.Json
опосредованно через ASP.NET Core, максимальный предел глубины по умолчанию составляет 32. Значение по умолчанию будет таким же, как для привязки модели, и задаваться в классе JsonOptions.
Строки JSON (имена свойств и строковые значения)
Во время десериализации Newtonsoft.Json
принимает имена свойств, заключенные в двойные кавычки, одинарные кавычки или без кавычек. Он принимает строковые значения, заключенные в двойные кавычки или одинарные кавычки. Например, Newtonsoft.Json
принимает следующий код JSON:
{
"name1": "value",
'name2': "value",
name3: 'value'
}
System.Text.Json
принимает имена свойств и строковые значения только в двойных кавычках, так как этот формат требуется спецификацией RFC 8259 и является единственным форматом, который считается допустимым JSON.
Значение, заключенное в одинарные кавычки, приводит к исключению JsonException со следующим сообщением:
''' is an invalid start of a value.
Нестроковые значения для строковых свойств
Newtonsoft.Json
принимает нестроковые значения, например числа или литералы true
и false
, для десериализации в свойства строкового типа. Ниже приведен пример JSON, который Newtonsoft.Json
успешно десериализует в следующий класс:
{
"String1": 1,
"String2": true,
"String3": false
}
public class ExampleClass
{
public string String1 { get; set; }
public string String2 { get; set; }
public string String3 { get; set; }
}
System.Text.Json
не выполняет десериализацию нестроковых значений в строковые свойства. Нестроковое значение, полученное для строкового поля, приводит к исключению JsonException со следующим сообщением:
The JSON value could not be converted to System.String.
Сценарии с использованием JsonSerializer
Некоторые из приведенных ниже сценариев не поддерживаются встроенными функциями, но возможны обходные пути. В качестве обходных путей можно использовать пользовательские преобразователи, которые могут не обеспечивать полное равенство с функциями Newtonsoft.Json
. Для некоторых случаев приведены примеры кода. Если вы используете эти функции Newtonsoft.Json
, для миграции потребуется внести изменения в объектные модели .NET или другие части кода.
Для некоторых из приведенных ниже сценариев обходные пути являются нецелесообразными или невозможными. Если вы используете эти функции Newtonsoft.Json
, миграция будет невозможна без существенных изменений.
Разрешение или запись чисел в кавычках
Newtonsoft.Json
может сериализовать или десериализовать числа, представленные строками JSON (заключенные в кавычки). Например, он может принимать {"DegreesCelsius":"23"}
вместо {"DegreesCelsius":23}
. Чтобы включить это поведение в System.Text.Json, задайте для свойства JsonSerializerOptions.NumberHandling значение WriteAsString или AllowReadingFromString или используйте атрибут [JsonNumberHandling].
Если вы используете System.Text.Json
косвенно с помощью ASP.NET Core, вам не нужно ничего делать для получения поведения, аналогичного Newtonsoft.Json
. ASP.NET Core указывает стандартные значения для веб-приложений при использовании System.Text.Json
. Стандартные значения для веб-служб допускают заключенные в кавычки числа.
Дополнительные сведения см. в разделе Разрешение или запись чисел в кавычках.
Указание конструктора для использования при десериализации
Атрибут Newtonsoft.Json
[JsonConstructor]
позволяет указать, какой конструктор вызывать при десериализации в POCO.
System.Text.Json
также имеет атрибут [JsonConstructor]. Дополнительные сведения см. в разделе Неизменяемые типы и записи.
Условное игнорирование свойства
Newtonsoft.Json
имеет несколько способов условно игнорировать свойство при сериализации или десериализации:
DefaultContractResolver
позволяет выбирать свойства для включения или игнорирования на основе произвольных критериев.- Параметры
NullValueHandling
иDefaultValueHandling
дляJsonSerializerSettings
позволяют указать, что все свойства со значением NULL или значениями по умолчанию должны игнорироваться. - Параметры
NullValueHandling
иDefaultValueHandling
атрибута[JsonProperty]
позволяют указать отдельные свойства, которые должны игнорироваться при установке значения NULL или значения по умолчанию.
System.Text.Json предоставляет следующие способы игнорирования свойств или полей при сериализации:
- Атрибут [JsonIgnore] в свойстве приводит к исключению свойства из JSON во время сериализации.
- Глобальный параметр IgnoreReadOnlyProperties позволяет игнорировать все свойства "только для чтения".
- Если вы включаете поля, глобальный JsonSerializerOptions.IgnoreReadOnlyFields параметр позволяет игнорировать все поля, доступные только для чтения.
- Глобальный параметр
DefaultIgnoreCondition
позволяет игнорировать все свойства типа значения, имеющие значения по умолчанию, или игнорировать все свойства ссылочного типа, имеющие значения NULL.
Кроме того, в .NET 7 и более поздних версиях можно настроить контракт JSON, чтобы игнорировать свойства на основе произвольных критериев. Дополнительные сведения см. в разделе "Пользовательские контракты".
Эти параметры не позволяют игнорировать выбранные свойства на основе произвольных критериев, которые оцениваются во время выполнения.
Открытые и не открытые поля
Newtonsoft.Json
может выполнять сериализацию и десериализацию полей, а также свойств.
Чтобы включить общие поля при сериализации или десериализации, используйте в System.Text.Json глобальный параметр JsonSerializerOptions.IncludeFields или атрибут [JsonInclude]. Пример см. в разделе Включение полей.
Сохранение ссылок на объекты и обработка циклов
По умолчанию Newtonsoft.Json
сериализуется по значению. Например, если объект включает два свойства, которые содержат ссылку на один и тот же объект Person
, значения свойств этого объекта Person
дублируются в JSON.
У Newtonsoft.Json
параметр PreserveReferencesHandling
имеет значение JsonSerializerSettings
, что позволяет выполнять сериализацию по ссылке:
- Метаданные идентификатора добавляются в JSON, созданный для первого объекта
Person
. - JSON, созданный для второго объекта
Person
, содержит ссылку на этот идентификатор вместо значений свойств.
Newtonsoft.Json
также имеет параметр ReferenceLoopHandling
, который позволяет игнорировать циклические ссылки, а не создавать исключение.
Для сохранения ссылок и обработки циклических ссылок System.Text.Json задайте для свойства JsonSerializerOptions.ReferenceHandler значение Preserve. Параметр ReferenceHandler.Preserve
эквивалентен PreserveReferencesHandling
= PreserveReferencesHandling.All
в Newtonsoft.Json
.
Параметр ReferenceHandler.IgnoreCycles
имеет поведение, аналогичное Newtonsoft.JsonReferenceLoopHandling.Ignore
. Одно из различий заключается в том, что System.Text.Json реализация заменяет циклы ссылок null
маркером JSON, а не игнорирует ссылку на объект. Дополнительные сведения см. в статье Пропуск циклических ссылок.
Newtonsoft.JsonКак и в ReferenceResolver, System.Text.Json.Serialization.ReferenceResolver класс определяет поведение сохранения ссылок на сериализацию и десериализацию. Создайте производный класс, чтобы указать настраиваемое поведение. Пример см. в статье GuidReferenceResolver.
Некоторые связанные Newtonsoft.Json
функции не поддерживаются:
Дополнительные сведения см. в разделе Сохранение ссылок и обработка циклических ссылок.
Словарь с ключом, не являющимся строкой
И Newtonsoft.Json
, и System.Text.Json
поддерживают коллекции типа Dictionary<TKey, TValue>
. Однако в System.Text.Json
ней TKey
должен быть примитивным типом, а не пользовательским типом. Дополнительные сведения см. в разделе "Поддерживаемые типы ключей".
Внимание
Десериализация в месте, где TKey
типизируется как что-либо, отличное от того, string
что может привести к уязвимости Dictionary<TKey, TValue>
безопасности в используемом приложении. Дополнительные сведения см. в статье dotnet/runtime#4761.
Типы без встроенной поддержки
System.Text.Json не предоставляет встроенную поддержку для следующих типов:
- DataTable и связанные типы (дополнительные сведения см. в разделе "Поддерживаемые типы коллекций")
- ExpandoObject
- TimeZoneInfo
- BigInteger
- DBNull
- Type
- ValueTuple и связанные с ним универсальные типы
Пользовательские преобразователи можно реализовать для типов, у которых нет встроенной поддержки.
Полиморфная сериализация
Newtonsoft.Json
автоматически выполняет полиморфную сериализацию. Начиная с .NET 7, System.Text.Json поддерживает полиморфную сериализацию с помощью атрибута JsonDerivedTypeAttribute . Дополнительные сведения см. в разделе "Сериализация свойств производных классов".
Полиморфная десериализация
Newtonsoft.Json
имеет параметр, который добавляет метаданные TypeNameHandling
имени типа в JSON при сериализации. Он использует метаданные во время десериализации для выполнения полиморфной десериализации. Начиная с .NET 7, System.Text.Json использует дискриминационные сведения о типе для выполнения полиморфной десериализации. Эти метаданные создаются в формате JSON, а затем используются во время десериализации, чтобы определить, следует ли десериализовать базовый тип или производный тип. Дополнительные сведения см. в разделе "Сериализация свойств производных классов".
Чтобы поддерживать полиморфную десериализацию в более ранних версиях .NET, создайте преобразователь, например пример в руководстве по написанию пользовательских преобразователей.
Десериализация строковых значений перечисления
По умолчанию не поддерживает десериализацию System.Text.Json строковых значений перечисления, в то время как это Newtonsoft.Json
происходит. Например, следующий код вызывает JsonExceptionисключение:
string json = "{ \"Text\": \"Hello\", \"Enum\": \"Two\" }";
var _ = JsonSerializer.Deserialize<MyObj>(json); // Throws exception.
class MyObj
{
public string Text { get; set; } = "";
public MyEnum Enum { get; set; }
}
enum MyEnum
{
One,
Two,
Three
}
Однако можно включить десериализацию строковых значений перечисления с помощью преобразователя JsonStringEnumConverter . Дополнительные сведения см. в разделе Перечисления в виде строк.
Десериализация свойств объекта
Когда Newtonsoft.Json
выполняет десериализацию в Object, он:
- Выводит типы примитивных значений в полезных данных JSON (кроме
null
) и возвращает хранимыеstring
,long
,double
,boolean
илиDateTime
в виде упакованного объекта. Примитивные значения — это отдельные значения JSON, такие как число JSON, строка,true
,false
илиnull
. - Возвращает
JObject
илиJArray
для сложных значений в полезных данных JSON. Сложные значения являются коллекциями пар "ключ-значение" JSON в фигурных скобках ({}
) или списками значений в квадратных скобках ([]
). Свойства и значения в фигурных или квадратных скобках могут иметь дополнительные свойства или значения. - Возвращает пустую ссылку, если полезная нагрузка содержит литерал
null
JSON.
System.Text.Json хранит упакованный JsonElement
как для простых, так и для сложных значений при десериализации в Object, например:
- Свойство
object
. - Значение словаря
object
. - Тип массива
object
. - Корневой
object
.
Однако System.Text.Json
обрабатывает null
так же, как Newtonsoft.Json
, и возвращает пустую ссылку, если полезная нагрузка содержит литерал null
JSON.
Чтобы реализовать определение типа для свойств object
, создайте преобразователь, как в примере в разделе Написание пользовательских преобразователей.
Десериализация значения NULL в тип, не допускающий значения NULL
Newtonsoft.Json
не создает исключение в следующем сценарии:
NullValueHandling
имеет значениеIgnore
.- Во время десериализации JSON содержит значение NULL для типа значения, не допускающего значения NULL.
В том же сценарии System.Text.Json создает исключение. (Соответствующий параметр обработки значений NULL в System.Text.Json
— JsonSerializerOptions.IgnoreNullValues = true
.)
Если вы владеете типом целевого объекта, лучшим обходным решением будет сделать соответствующее свойство допускающим значение NULL (например, изменить int
на int?
).
Еще один обходной путь — сделать преобразователь для типа, как в следующем примере, который обрабатывает значения NULL для типов DateTimeOffset
:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class DateTimeOffsetNullHandlingConverter : JsonConverter<DateTimeOffset>
{
public override DateTimeOffset Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) =>
reader.TokenType == JsonTokenType.Null
? default
: reader.GetDateTimeOffset();
public override void Write(
Utf8JsonWriter writer,
DateTimeOffset dateTimeValue,
JsonSerializerOptions options) =>
writer.WriteStringValue(dateTimeValue);
}
}
Зарегистрируйте этот пользовательский преобразователь, используя атрибут для свойства или добавив преобразователь в коллекцию Converters.
Примечание. Предыдущий преобразователь обрабатывает значения NULL по-разному , чем Newtonsoft.Json
для POCOs, которые указывают значения по умолчанию. Например, следующий код представляет целевой объект:
public class WeatherForecastWithDefault
{
public WeatherForecastWithDefault()
{
Date = DateTimeOffset.Parse("2001-01-01");
Summary = "No summary";
}
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string Summary { get; set; }
}
Предположим, что следующий JSON десериализуется с помощью предыдущего преобразователя:
{
"Date": null,
"TemperatureCelsius": 25,
"Summary": null
}
После десериализации свойство Date
имеет значение 1/1/0001 (default(DateTimeOffset)
), то есть значение, заданное в конструкторе, перезаписывается. При наличии одних и тех же POCO и JSON десериализация Newtonsoft.Json
оставляет значение 1/1/2001 в свойстве Date
.
Десериализация в неизменяемые классы и структуры
Newtonsoft.Json
может выполнять десериализацию в неизменяемые классы и структуры, так как он может использовать конструкторы с параметрами.
Чтобы указать использование параметризованного конструктора, используйте вSystem.Text.Json атрибут [JsonConstructor]. Записи в C# 9 также являются неизменяемыми и поддерживаются в качестве целей десериализации. Дополнительные сведения см. в разделе Неизменяемые типы и записи.
Обязательные свойства
В Newtonsoft.Json
вы указываете, что свойство является обязательным, задав Required
для атрибута [JsonProperty]
. Newtonsoft.Json
создает исключение, если в JSON не получено значение для свойства, помеченного как обязательное.
Начиная с .NET 7, можно использовать модификатор C# required
или JsonRequiredAttribute атрибут в обязательном свойстве. System.Text.Json вызывает исключение, если полезные данные JSON не содержат значения для помеченного свойства. Дополнительные сведения см. в разделе "Обязательные свойства".
System.Text.Json не создает исключение, если для одного из свойств целевого типа не получено значение. Например, у вас есть класс WeatherForecast
:
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
Следующий JSON десериализуется без ошибки:
{
"TemperatureCelsius": 25,
"Summary": "Hot"
}
Чтобы сделать десериализацию неудачной, если свойство не Date
находится в JSON, выберите один из следующих вариантов:
- Используйте .NET 7 или более позднюю версию System.Text.Json пакета и добавьте
required
модификатор (доступный начиная с C# 11) или JsonRequiredAttribute атрибут в свойство. - Реализация пользовательского преобразователя.
- Реализуйте обратный вызов (.NET 6 и более поздние
OnDeserialized
версии).
Следующий пример кода преобразователя создает исключение, если после десериализации свойство Date
не задано:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class WeatherForecastRequiredPropertyConverter : JsonConverter<WeatherForecast>
{
public override WeatherForecast Read(
ref Utf8JsonReader reader,
Type type,
JsonSerializerOptions options)
{
// Don't pass in options when recursively calling Deserialize.
WeatherForecast forecast = JsonSerializer.Deserialize<WeatherForecast>(ref reader)!;
// Check for required fields set by values in JSON
return forecast!.Date == default
? throw new JsonException("Required property not received in the JSON")
: forecast;
}
public override void Write(
Utf8JsonWriter writer,
WeatherForecast forecast, JsonSerializerOptions options)
{
// Don't pass in options when recursively calling Serialize.
JsonSerializer.Serialize(writer, forecast);
}
}
}
Зарегистрируйте этот пользовательский преобразователь, добавив его в коллекцию JsonSerializerOptions.Converters.
Для использования этого шаблона рекурсивного вызова преобразователя необходимо зарегистрировать преобразователь с помощью JsonSerializerOptions, а не с помощью атрибута. При регистрации с помощью атрибута пользовательский преобразователь рекурсивно вызывает сам себя. Результатом является бесконечный цикл, который заканчивается исключением переполнения стека.
При регистрации преобразователя с помощью объекта options следует избегать бесконечного цикла, поэтому не передавайте объект options при рекурсивном вызове Serialize или Deserialize. Объект options содержит коллекцию Converters. Если передать его в Serialize
или Deserialize
, пользовательский преобразователь вызывает сам себя и делает бесконечный цикл, который приводит к исключению переполнения стека. Если параметры по умолчанию нецелесообразны, создайте новый экземпляр параметров с нужными настройками. Этот подход отнимет много времени, так как каждый новый экземпляр кэшируется независимо.
Существует альтернативный шаблон, который может использовать регистрацию JsonConverterAttribute
в классе, подлежащем преобразованию. В таком случае код преобразователя вызывает Serialize
или Deserialize
для класса, производного от класса, который требуется преобразовать. К производному классу не применен JsonConverterAttribute
. В следующем примере этого варианта:
WeatherForecastWithRequiredPropertyConverterAttribute
— класс, который подлежит десериализации и к которому примененJsonConverterAttribute
;WeatherForecastWithoutRequiredPropertyConverterAttribute
— производный класс без атрибута преобразователя.- Код в вызовах
Serialize
преобразователя иDeserialize
наWeatherForecastWithoutRequiredPropertyConverterAttribute
ней, чтобы избежать бесконечного цикла. Этот подход к сериализации приводит к снижению производительности, так как создается дополнительный объект и копируются значения свойств.
Ниже приведены типы WeatherForecast*
.
[JsonConverter(typeof(WeatherForecastRequiredPropertyConverterForAttributeRegistration))]
public class WeatherForecastWithRequiredPropertyConverterAttribute
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
public class WeatherForecastWithoutRequiredPropertyConverterAttribute :
WeatherForecastWithRequiredPropertyConverterAttribute
{
}
Ниже приведен преобразователь.
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class WeatherForecastRequiredPropertyConverterForAttributeRegistration :
JsonConverter<WeatherForecastWithRequiredPropertyConverterAttribute>
{
public override WeatherForecastWithRequiredPropertyConverterAttribute Read(
ref Utf8JsonReader reader,
Type type,
JsonSerializerOptions options)
{
// OK to pass in options when recursively calling Deserialize.
WeatherForecastWithRequiredPropertyConverterAttribute forecast =
JsonSerializer.Deserialize<WeatherForecastWithoutRequiredPropertyConverterAttribute>(
ref reader,
options)!;
// Check for required fields set by values in JSON.
return forecast!.Date == default
? throw new JsonException("Required property not received in the JSON")
: forecast;
}
public override void Write(
Utf8JsonWriter writer,
WeatherForecastWithRequiredPropertyConverterAttribute forecast,
JsonSerializerOptions options)
{
var weatherForecastWithoutConverterAttributeOnClass =
new WeatherForecastWithoutRequiredPropertyConverterAttribute
{
Date = forecast.Date,
TemperatureCelsius = forecast.TemperatureCelsius,
Summary = forecast.Summary
};
// OK to pass in options when recursively calling Serialize.
JsonSerializer.Serialize(
writer,
weatherForecastWithoutConverterAttributeOnClass,
options);
}
}
}
Если необходимо обрабатывать атрибуты (например, [JsonIgnore] или различные параметры (например, пользовательские кодировщики)), преобразователю свойств потребуется дополнительная логика. Кроме того, пример кода не обрабатывает свойства, для которых в конструкторе задано значение по умолчанию. И этот подход не различает следующие сценарии:
- В JSON отсутствует свойство.
- Свойство для типа, не допускающего значения NULL, содержится в JSON, но значение является значением по умолчанию для типа, например ноль для
int
. - Свойство для типа значения, допускающего значение NULL, содержится в JSON, но значение равно NULL.
Примечание.
Если вы используете System.Text.Json из контроллера ASP.NET Core, вы можете использовать [Required]
атрибут для свойств класса модели вместо реализации System.Text.Json преобразователя.
Указание формата даты
Newtonsoft.Json
предоставляет несколько способов управления сериализацией и десериализации свойств DateTime
и типов DateTimeOffset
:
- Параметр
DateTimeZoneHandling
можно использовать для сериализации всех значенийDateTime
как даты в формате UTC. - Параметры
DateFormatString
и преобразователиDateTime
можно использовать для настройки формата строк даты.
System.Text.Json поддерживает ISO 8601-1:2019, включая профиль RFC 3339. Этот формат широко используется, является однозначным и точно выполняет круговые пути. Чтобы использовать любой другой формат, создайте пользовательский преобразователь. Например, следующие преобразователи сериализуют и десериализируют JSON, использующие формат эпохи Unix с смещением часового пояса или без нее (например/Date(1590863400000-0700)/
, значения):/Date(1590863400000)/
sealed class UnixEpochDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
static readonly DateTimeOffset s_epoch = new(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
static readonly Regex s_regex = new("^/Date\\(([+-]*\\d+)([+-])(\\d{2})(\\d{2})\\)/$", RegexOptions.CultureInvariant);
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
if (
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime)
|| !int.TryParse(match.Groups[3].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int hours)
|| !int.TryParse(match.Groups[4].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int minutes))
{
throw new JsonException();
}
int sign = match.Groups[2].Value[0] == '+' ? 1 : -1;
TimeSpan utcOffset = new(hours * sign, minutes * sign, 0);
return s_epoch.AddMilliseconds(unixTime).ToOffset(utcOffset);
}
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
TimeSpan utcOffset = value.Offset;
string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime}{(utcOffset >= TimeSpan.Zero ? "+" : "-")}{utcOffset:hhmm})/");
writer.WriteStringValue(formatted);
}
}
sealed class UnixEpochDateTimeConverter : JsonConverter<DateTime>
{
static readonly DateTime s_epoch = new(1970, 1, 1, 0, 0, 0);
static readonly Regex s_regex = new("^/Date\\(([+-]*\\d+)\\)/$", RegexOptions.CultureInvariant);
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
if (
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime))
{
throw new JsonException();
}
return s_epoch.AddMilliseconds(unixTime);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime})/");
writer.WriteStringValue(formatted);
}
}
Дополнительные сведения см. в разделе Поддержка DateTime и DateTimeOffset в System.Text.Json.
Обратные вызовы
Newtonsoft.Json
позволяет выполнять пользовательский код в нескольких точках процесса сериализации или десериализации:
- OnDeserializing (в начале десериализации объекта)
- OnDeserialized (после десериализации объекта)
- OnSerializing (в начале сериализации объекта)
- OnSerialized (после сериализации объекта)
System.Text.Json предоставляет те же уведомления во время сериализации и десериализации. Чтобы использовать их, реализуйте один или несколько следующих интерфейсов из System.Text.Json.Serialization пространства имен:
Ниже приведен пример, который проверяет значение NULL и записывает сообщения в начале и конце сериализации и десериализации:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Callbacks
{
public class WeatherForecast :
IJsonOnDeserializing, IJsonOnDeserialized,
IJsonOnSerializing, IJsonOnSerialized
{
public DateTime Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
void IJsonOnDeserializing.OnDeserializing() => Console.WriteLine("\nBegin deserializing");
void IJsonOnDeserialized.OnDeserialized()
{
Validate();
Console.WriteLine("Finished deserializing");
}
void IJsonOnSerializing.OnSerializing()
{
Console.WriteLine("Begin serializing");
Validate();
}
void IJsonOnSerialized.OnSerialized() => Console.WriteLine("Finished serializing");
private void Validate()
{
if (Summary is null)
{
Console.WriteLine("The 'Summary' property is 'null'.");
}
}
}
public class Program
{
public static void Main()
{
var weatherForecast = new WeatherForecast
{
Date = DateTime.Parse("2019-08-01"),
TemperatureCelsius = 25,
};
string jsonString = JsonSerializer.Serialize(weatherForecast);
Console.WriteLine(jsonString);
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString);
Console.WriteLine($"Date={weatherForecast?.Date}");
Console.WriteLine($"TemperatureCelsius={weatherForecast?.TemperatureCelsius}");
Console.WriteLine($"Summary={weatherForecast?.Summary}");
}
}
}
// output:
//Begin serializing
//The 'Summary' property is 'null'.
//Finished serializing
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":null}
//Begin deserializing
//The 'Summary' property is 'null'.
//Finished deserializing
//Date=8/1/2019 12:00:00 AM
//TemperatureCelsius = 25
//Summary=
Код OnDeserializing
не имеет доступа к новому экземпляру POCO. Чтобы управлять новым экземпляром POCO в начале десериализации, вставьте этот код в конструктор POCO.
Методы задания и методы получения свойств, которые не являются общими
Newtonsoft.Json
может использовать методы задания и получения частных и внутренних свойств с помощью атрибута JsonProperty
.
System.Text.Json поддерживает методы задания и получения частных и внутренних свойств с помощью атрибута [JsonInclude]. Пример кода см. в разделе Методы доступа к свойствам, не являющимся общедоступными.
Заполнение существующих объектов
Метод JsonConvert.PopulateObject
в Newtonsoft.Json
десериализует документ JSON в существующий экземпляр класса вместо создания нового экземпляра. System.Text.Json всегда создает новый экземпляр целевого типа с помощью открытого конструктора без параметров по умолчанию. Пользовательские преобразователи можно десериализовать в существующий экземпляр.
Повторное использование вместо замены свойств
Начиная с .NET 8, System.Text.Json поддерживает повторное использование инициализированных свойств, а не их замены. Существуют некоторые различия в поведении, о которых можно прочитать в предложении API.
Дополнительные сведения см. в разделе "Заполнение инициализированных свойств".
Этот ObjectCreationHandling
параметр Newtonsoft.Json
позволяет указать, что объекты в свойствах следует повторно использовать, а не заменить во время десериализации. System.Text.Json всегда заменяет объекты в свойствах. Пользовательские преобразователи могут предоставить эту функцию или обновить до .NET 8, которая предоставляет функциональность заполнения.
Заполнение свойств без наборов
Начиная с .NET 8, System.Text.Json поддерживает заполнение свойств, включая те, у которых нет набора. Дополнительные сведения см. в разделе "Заполнение инициализированных свойств".
Во время десериализации Newtonsoft.Json
добавляет объекты в коллекцию, даже если свойство не имеет метода задания. System.Text.Json игнорирует свойства, у которых нет методов задания. Пользовательские преобразователи могут предоставлять эту функцию или обновлять до .NET 8, которая может заполнять свойства только для чтения.
Политика именования регистра змеи
System.Text.Json включает встроенную политику именования для змеиного дела. Однако для некоторых входных данных существуют некоторые различия Newtonsoft.Json
в поведении. В следующей таблице показаны некоторые из этих различий при преобразовании входных данных с помощью JsonNamingPolicy.SnakeCaseLower политики.
Входные данные | Newtonsoft.Json результат | System.Text.Json результат |
---|---|---|
AB1 | "a_b1" | Ab1 |
"SHA512Managed" | "sh_a512_managed" | "sha512_managed" |
"abc123DEF456" | "abc123_de_f456" | "abc123_def456" |
"KEBAB-CASE" | "keba_b-_case" | "kebab-case" |
Единственная встроенная политика именования свойств в System.Text.Json случае верблюда. Newtonsoft.Json
может преобразовать имена свойств в регистр змеи. Настраиваемая политика именования может предоставить эту функцию или обновить до .NET 8 или более поздней версии, которая включает встроенные политики именования змеи.
Атрибуты System.Runtime.Serialization
System.Runtime.Serialization такие атрибуты, как DataContractAttribute, DataMemberAttributeи IgnoreDataMemberAttribute позволяют определить контракт данных. Контракт данных - формальное соглашение между службой и клиентом, абстрактно описывающее данные, обмен которыми происходит. Контракт данных точно определяет, какие свойства сериализуются для обмена.
System.Text.Json не поддерживает встроенные атрибуты. Однако начиная с .NET 7 можно использовать настраиваемый сопоставитель типов для добавления поддержки. Пример см. в разделе ZCS. DataContractResolver.
Числа восьмеричной системы
Newtonsoft.Json
обрабатывает числа с начальным нулем как восьмеричные числа. System.Text.Json не допускает начальные нули, так как спецификация RFC 8259 не разрешает их.
Обработка отсутствующих элементов
Если json, десериализированный включает свойства, отсутствующие в целевом типе, Newtonsoft.Json
можно настроить для создания исключений. По умолчанию System.Text.Json игнорирует дополнительные свойства в формате JSON, за исключением использования атрибута [JsonExtensionData].
В .NET 8 и более поздних версиях можно настроить выбор того, следует ли пропускать или запрещать несопоставленные свойства JSON с помощью одного из следующих средств:
- Примените атрибут к типу JsonUnmappedMemberHandlingAttribute , к к который выполняется десериализация.
- Чтобы задать предпочтения глобально, задайте JsonSerializerOptions.UnmappedMemberHandling свойство. Или для создания источника задайте JsonSourceGenerationOptionsAttribute.UnmappedMemberHandling свойство и примените атрибут к классу JsonSerializerContext .
- JsonTypeInfo.UnmappedMemberHandling Настройте свойство.
JsonObjectAttribute
Newtonsoft.Json
имеет атрибут, JsonObjectAttribute
который можно применить на уровне типа для управления сериализующимися элементами, способами null
обработки значений и необходимости всех элементов. System.Text.Json не имеет эквивалентного атрибута, который можно применить к типу. Для некоторых действий, таких как null
обработка значений, можно настроить одно и то же поведение в глобальном JsonSerializerOptions или отдельном свойстве.
Рассмотрим следующий пример, который используется Newtonsoft.Json.JsonObjectAttribute
для указания того, что все null
свойства должны игнорироваться:
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class Person { ... }
В System.Text.Jsonэтом случае можно задать поведение для всех типов и свойств:
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
string json = JsonSerializer.Serialize<Person>(person, options);
Или можно задать поведение для каждого свойства отдельно:
public class Person
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Name { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? Age { get; set; }
}
Далее рассмотрим следующий пример, который используется Newtonsoft.Json.JsonObjectAttribute
для указания того, что все свойства члена должны присутствовать в JSON:
[JsonObject(ItemRequired = Required.Always)]
public class Person { ... }
Вы можете добиться того же поведения, System.Text.Json добавив модификатор C# required
или в каждое JsonRequiredAttribute свойство. Дополнительные сведения см. в разделе "Обязательные свойства".
public class Person
{
[JsonRequired]
public string? Name { get; set; }
public required int? Age { get; set; }
}
TraceWriter
Newtonsoft.Json
позволяет выполнять отладку с помощью TraceWriter
для просмотра журналов, созданных при сериализации или десериализации. System.Text.Json не ведет журнал.
JsonDocument и JsonElement в сравнении с JToken (например, JObject, JArray)
System.Text.Json.JsonDocument предоставляет возможность выполнять синтаксический анализ и сборку модели DOM только для чтения из существующих полезных данных JSON. Модель DOM предоставляет произвольный доступ к данным в полезных данных JSON. Доступ к элементам JSON, составляющим полезные данные, можно получить с помощью типа JsonElement. Тип JsonElement
предоставляет интерфейсы API для преобразования текста JSON в общие типы .NET. JsonDocument
предоставляет свойство RootElement.
Начиная с .NET 6, можно проанализировать и создать мутируемый DOM из существующих полезных данных JSON с помощью JsonNode типа и других типов в System.Text.Json.Nodes пространстве имен. Дополнительные сведения см. в разделе "Использование JsonNode
".
JsonDocument является IDisposable
JsonDocument
создает выполняющееся в памяти представление данных в едином буфере. Таким образом, в отличие от JObject
или JArray
из Newtonsoft.Json
, тип JsonDocument
реализует IDisposable
и должен использоваться внутри блока using. Дополнительные сведения см. в разделе JsonDocument — IDisposable.
JsonDocument доступен только для чтения
Модель DOM System.Text.Json не может добавлять, удалять или изменять элементы JSON. Он разработан таким образом, чтобы обеспечить производительность и сократить выделение для анализа общих размеров полезных данных JSON (т < . е. 1 МБ).
JsonElement является структурой объединения
JsonDocument
предоставляет RootElement
свойство типа JsonElement, которое является типом структуры объединения, которая охватывает любой элемент JSON. Newtonsoft.Json
использует выделенные иерархические типы, такие как JObject
, JArray
JToken
и т. д. JsonElement
можно использовать для поиска и перечисления, а с помощью JsonElement
можно материализовывать элементы JSON в типы .NET.
Начиная с .NET 6, можно использовать JsonNode тип и типы в пространстве имен, соответствующего System.Text.Json.Nodes JObject
, JArray
и JToken
. Дополнительные сведения см. в разделе "Использование JsonNode
".
Поиск вложенных элементов в JsonDocument и JsonElement
Поиск токенов JSON с помощью JObject
или JArray
из Newtonsoft.Json
, как правило, выполняется относительно быстро, так как они присутствуют в словаре. По сравнению с этим поиски JsonElement
требуют последовательного поиска свойств и, следовательно, относительно медленны (например, при использовании TryGetProperty
). System.Text.Json предназначен для сокращения времени начального анализа, а не времени поиска. Дополнительные сведения см. в разделе "Поиск jsonDocument и JsonElement" для вложенных элементов.
Utf8JsonReader и JsonTextReader
System.Text.Json.Utf8JsonReader— это высокопроизводительное, низкое выделение, доступное только для чтения с пересылкой для текста JSON в кодировке UTF-8, считываемое из байта ReadOnlySpan>< или байта> ReadOnlySequence.< Utf8JsonReader
— это низкоуровневый тип, с помощью которого можно создавать пользовательские средства синтаксического анализа и десериализаторы.
Utf8JsonReader является структурой ссылок
Newtonsoft.Json
В JsonTextReader
этом классе. Тип Utf8JsonReader
отличается в том, что это структура ссылок. Дополнительные сведения см. в разделе об ограничениях структуры ref для Utf8JsonReader.
Считывание значений NULL в типы значений, допускающие значения NULL
Newtonsoft.Json
предоставляет API, которые возвращают Nullable<T>, например ReadAsBoolean
, который обрабатывает Null
TokenType
, возвращая bool?
. Встроенные API System.Text.Json
возвращают только типы значений, не допускающие значения NULL. Дополнительные сведения см. в разделе "Чтение значений NULL" в типы значений, допускающих значение NULL.
Многоцелевой объект для чтения JSON
Если необходимо продолжить использование Newtonsoft.Json
для определенных целевых платформ, можно выбрать несколько версий и создать две реализации. Однако это нестандартный подход, и потребуется несколько #ifdefs
и дублирование источника. Одним из способов совместного использования максимально возможного объема кода является создание оболочки вокруг ref struct
и Utf8JsonReader Newtonsoft.Json.JsonTextReader
. Эта оболочка будет объединять общедоступную контактную зону при изоляции различий в поведении. Это позволяет изолировать изменения, сведя их, в основном, к созданию типа, а также передаче нового типа по ссылке. Это шаблон, которому следует библиотека Microsoft.Extensions.DependencyModel:
Utf8JsonWriter и JsonTextWriter
System.Text.Json.Utf8JsonWriter — это высокопроизводительный способ записать текст JSON в кодировке UTF-8 из распространенных типов .NET, например String
, Int32
и DateTime
. Модуль записи — это низкоуровневый тип, с помощью которого можно создавать пользовательские сериализаторы.
Запись необработанных значений
Newtonsoft.Json
WriteRawValue
имеет метод, который записывает необработанный JSON, где ожидается значение. System.Text.Jsonимеет прямой эквивалент: Utf8JsonWriter.WriteRawValue Дополнительные сведения см. в статье "Запись необработанного JSON".
Настройка формата JSON
JsonTextWriter
включает следующие параметры, для которых Utf8JsonWriter не имеет эквивалента:
- QuoteChar — указывает символ, используемый для заключения строковых значений.
Utf8JsonWriter
всегда использует двойные кавычки. - QuoteName — указывает, следует ли заключать имена свойств в кавычки.
Utf8JsonWriter
всегда заключает их в кавычки.
Начиная с .NET 9, можно настроить символ отступа и размер для Utf8JsonWriter использования параметров, предоставляемых структурой JsonWriterOptions :
JsonTextWriter
включает следующие параметры, для которых Utf8JsonWriter
не имеет эквивалента:
- Отступ — задает количество символов для отступа.
Utf8JsonWriter
всегда отступы по 2 символам. - IndentChar — указывает символ, используемый для отступа.
Utf8JsonWriter
всегда использует пробелы. - QuoteChar — указывает символ, используемый для заключения строковых значений.
Utf8JsonWriter
всегда использует двойные кавычки. - QuoteName — указывает, следует ли заключать имена свойств в кавычки.
Utf8JsonWriter
всегда заключает их в кавычки.
Не существует обходных решений, которые позволяют настроить JSON, созданный Utf8JsonWriter
такими методами.
Запись значений TimeSpan, URI или char
JsonTextWriter
предоставляет методы WriteValue
для значений TimeSpan, URI и char. Utf8JsonWriter
не имеет эквивалентных методов. Вместо этого следует отформатировать эти значения как строки (например, вызвав ToString()
) и вызвать WriteStringValue.
Многоцелевой объект для записи JSON
Если необходимо продолжить использование Newtonsoft.Json
для определенных целевых платформ, можно выбрать несколько версий и создать две реализации. Однако это нестандартный подход, и потребуется несколько #ifdefs
и дублирование источника. Одним из способов совместного использования кода является создание оболочки Utf8JsonWriter вокруг и Newtonsoft.Json.JsonTextWriter
. Эта оболочка будет объединять общедоступную контактную зону при изоляции различий в поведении. Это позволяет изолировать изменения и свести их, в основном, к созданию типа. Библиотека Microsoft.Extensions.DependencyModel следует:
TypeNameHandling.All не поддерживается
Решение исключить TypeNameHandling.All
эквивалентные функциональные System.Text.Json
возможности было намеренно. Чтобы полезные данные JSON указывали собственные сведения о типе, являются общим источником уязвимостей в веб-приложениях. В частности, настройка Newtonsoft.Json
с TypeNameHandling.All
помощью удаленного клиента позволяет внедрить целое исполняемое приложение в саму полезные данные JSON, чтобы во время десериализации веб-приложение извлекает и запускает внедренный код. Дополнительные сведения см. в пятницу 13-й атаки JSON в PowerPoint и пятницу 13-й атаки JSON.
Запросы пути JSON не поддерживаются
JsonDocument
DOM не поддерживает запросы с помощью пути JSON.
JsonNode В DOM каждый JsonNode
экземпляр имеет GetPath
метод, возвращающий путь к данному узлу. Но встроенный API не используется для обработки запросов на основе строк запроса пути JSON.
Дополнительные сведения см. в статье о проблеме dotnet/runtime #31068 GitHub.
Некоторые ограничения не настраиваемы
System.Text.Json задает ограничения, которые не могут быть изменены для некоторых значений, например максимальный размер маркера в символах (166 МБ) и в базе 64 (125 МБ). Дополнительные сведения см JsonConstants
. в исходном коде и проблеме GitHub dotnet/runtime #39953.
NaN, Бесконечность, -Бесконечность
Синтаксический NaN
Infinity
анализ Newtonsoft и -Infinity
токены строк JSON. С System.Text.Jsonпомощью , используйте JsonNumberHandling.AllowNamedFloatingPointLiterals. Сведения об использовании этого параметра см. в разделе "Разрешить" или "Записать номера" в кавычках.
Миграция с помощью GitHub Copilot
Вы можете получить справку по программированию из GitHub Copilot для преобразования кода в интегрированной среде разработки.
Если вы используете Visual Studio 2022 версии 17.8 или более поздней, вы можете попробовать GitHub Copilot на основе ИИ в Visual Studio , чтобы перенести Newtonsoft.Json
код на использование System.Text.Json
. Отправьте свой вопрос и код для преобразования в виде запроса в окне чата copilot, как показано в следующем примере.
Примечание.
GitHub Copilot работает СИ, поэтому возможны сюрпризы и ошибки. Обязательно проверьте любой созданный код или предложения. Дополнительные сведения об общем использовании GitHub Copilot, влиянии на продукты, надзоре и конфиденциальности см . в часто задаваемых вопросы о GitHub Copilot.
Пример запроса для Чата Copilot
convert the following code to use System.Text.Json
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2024, 08, 08);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string output = JsonConvert.SerializeObject(product);
Console.WriteLine(output);
Пример ответа Copilot Chat
To convert the code to use System.Text.Json, you can use the JsonSerializer class. Here's the updated code:
using System;
using System.Text.Json;
public class Product
{
public string Name { get; set; }
public DateTime ExpiryDate { get; set; }
public decimal Price { get; set; }
public string[] Sizes { get; set; }
}
public class Program
{
public static void Main()
{
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2024, 08, 08);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string output = JsonSerializer.Serialize(product);
Console.WriteLine(output);
}
}
This code uses System.Text.Json.JsonSerializer.Serialize to convert the Product object to a JSON string.
Обратите внимание, что результаты могут отличаться от того, что показано в этих примерах ответов. Модели искусственного интеллекта являются недетерминированными, что означает, что они могут возвращать разные ответы при появлении одного и того же вопроса. Это может быть связано с дополнительным обучением и адаптацией с течением времени, языковым изменением, изменениями в контексте, такими как журнал чата и многое другое.
Вы можете использовать функции чата, такие как команды косой черты, ссылки и потоки, чтобы задать намерение и получить лучшие ответы с контекстом области.
Например, если файл filename
кода открыт в интегрированной среде разработки, вы можете ссылаться на файл в запросе на Copilot Chat с параметром "преобразовать #filename
в использование System.Text.Json
". Вы также можете ссылаться на решение с помощью "преобразовать @workspace
в использование System.Text.Json
" в окне чата или в встроенном чате.