معاينة .NET Core 3.0 7
Asp.NET Web Apis ، عند إعادة قاموس فإنه يفشل مع NotSupportedException. لقد قمت بتضمين الاستثناء أدناه.
أيضًا ، تأخذ طريقة ControllerBase.BadRequest
ModelStateDictionary
، ولكن عندما يتم إرجاعها ، يتم تفجير جهاز التسلسل أيضًا مع NotSupportedException ، ولكن رسالة مختلفة قليلاً.
متى سيتم إضافة هذا الدعم؟ نظرًا لأن هذا تم دعمه في Json.net والمسلسلات الأخرى لفترة من الوقت ، آمل أن يكون هذا على الرادار.
أقدر حقًا حقيقة أنه يمكنني إعادة الاشتراك في استخدام Json.net ، لذا شكرًا جزيلاً لك على ذلك!
استثناء عند إرجاع قاموس
System.NotSupportedException: نوع المجموعة 'System.Collections.Generic.Dictionary`2 [System.Int32، System.String]' غير مدعوم.
في System.Text.Json.JsonClassInfo.GetElementType (النوع propertyType ، Type parentType ، MemberInfo memberInfo ، JsonSerializerOptions options)
في System.Text.
في System.Text.Json.JsonClassInfo.AddProperty (النوع propertyType و PropertyInfo propertyInfo و Type classType و JsonSerializerOptions options)
في System.Text.Json.JsonClassInfo.AddPolicyProperty (اكتب propertyType وخيارات JsonSerializerOptions)
في System.Text.Json.JsonClassInfo..ctor (نوع النوع ، خيارات JsonSerializerOptions)
في System.Text.Json.JsonSerializerOptions.GetOrAddClass (النوع classType)
في System.Text.Json.WriteStackFrame.Initialize (نوع النوع ، خيارات JsonSerializerOptions)
في System.Text.Json.JsonSerializer.WriteAsyncCore (Stream utf8Json، Object value، Type type، JsonSerializerOptions options، CancellationToken cancellationToken)
في Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync (سياق OutputFormatterWriteContext ، الترميز المحدد الترميز)
في Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync (سياق OutputFormatterWriteContext ، الترميز المحدد الترميز)
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow (سياق ResultExecutedContextSealed)
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext TFilter ، TFilterAsync
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters ()
--- نهاية تتبع المكدس من الموقع السابق حيث تم إلقاء الاستثناء ---
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.
في Microsoft.AspNetCore.Routing.EndpointMiddleware.
في Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke (سياق HttpContext)
في Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke (سياق HttpContext)
في Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke (سياق HttpContext)
في Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke (HttpContext httpContext)
في Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke (HttpContext httpContext ، ISwaggerProvider swaggerProvider)
في Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke (سياق HttpContext)
استثناء عند إرجاع BadRequest
System.NotSupportedException: نوع المجموعة "Microsoft.AspNetCore.Mvc.SerializableError" غير مدعوم.
في System.Text.Json.JsonClassInfo.GetElementType (النوع propertyType ، Type parentType ، MemberInfo memberInfo ، JsonSerializerOptions options)
في System.Text.
في System.Text.Json.JsonClassInfo.AddProperty (النوع propertyType و PropertyInfo propertyInfo و Type classType و JsonSerializerOptions options)
في System.Text.Json.JsonClassInfo.AddPolicyProperty (اكتب propertyType وخيارات JsonSerializerOptions)
في System.Text.Json.JsonClassInfo..ctor (نوع النوع ، خيارات JsonSerializerOptions)
في System.Text.Json.JsonSerializerOptions.GetOrAddClass (النوع classType)
في System.Text.Json.WriteStackFrame.Initialize (نوع النوع ، خيارات JsonSerializerOptions)
في System.Text.Json.JsonSerializer.WriteAsyncCore (Stream utf8Json، Object value، Type type، JsonSerializerOptions options، CancellationToken cancellationToken)
في Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync (سياق OutputFormatterWriteContext ، الترميز المحدد الترميز)
في Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync (سياق OutputFormatterWriteContext ، الترميز المحدد الترميز)
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow (سياق ResultExecutedContextSealed)
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext TFilter ، TFilterAsync
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters ()
--- نهاية تتبع المكدس من الموقع السابق حيث تم إلقاء الاستثناء ---
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.
في Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.
في Microsoft.AspNetCore.Routing.EndpointMiddleware.
في Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke (سياق HttpContext)
في Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke (سياق HttpContext)
في Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke (سياق HttpContext)
في Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke (HttpContext httpContext)
في Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke (HttpContext httpContext ، ISwaggerProvider swaggerProvider)
في Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke (سياق HttpContext)
كلا أخطاء "الاستثناء غير المدعوم" هي قيود داخل جهاز التسلسل المدمج وهي حسب التصميم (على الأقل لما يتم الشحن في 3.0).
متى سيتم إضافة هذا الدعم؟ نظرًا لأن هذا تم دعمه في Json.net والمسلسلات الأخرى لفترة من الوقت ، آمل أن يكون هذا على الرادار.
أقدر حقًا حقيقة أنه يمكنني إعادة الاشتراك في استخدام Json.net ، لذا شكرًا جزيلاً لك على ذلك!
هناك مجموعة من إمكانيات المتسلسل الموجودة على رادارنا لدعمها في vNext (حتى 5.0) وما بعده ، مع دعم القاموس المخصص كونها واحدة منها.
Asp.NET Web Apis ، عند إعادة قاموس فإنه يفشل مع NotSupportedException
عند التسلسل ، يتم دعم Dictionary<string, TValue>
اليوم (أي TKeys التي هي سلسلة). قاموسك هو <int, string>
وهو غير مدعوم.
https://github.com/dotnet/corefx/blob/93d7aa1c1737b6da29d04b78557215e18eb786d4/src/System.Text.Json/tests/Serialization/DictionaryTests.cs#L385 -L390
steveharter ، layomia - هل هناك حل بديل محتمل هنا في هذه الأثناء؟ ما الذي يتطلبه الأمر لإضافة دعم لقاموس بدون سلسلة مفاتيح داخل المسلسل لـ 5.0؟
System.NotSupportedException: نوع المجموعة "Microsoft.AspNetCore.Mvc.SerializableError" غير مدعوم.
~ إضافة دعم لنوع مثل SerializableError لم يكن على الرادار الخاص بي. pranavkm ، rynowak - ما هو السياق هنا؟ لست على دراية بـ ModelStateDictionary
، فهل يمكن دعم ذلك داخل mvc نفسها باستخدام محول مخصص؟ ~
تحرير: لا تهتم ، هذا ثابت بالفعل.
System.NotSupportedException: نوع المجموعة "Microsoft.AspNetCore.Mvc.SerializableError" غير مدعوم.
كانت هذه مشكلة معروفة https://github.com/aspnet/AspNetCore/issues/11459 تم إصلاحها مؤخرًا (كجزء من المعاينة 8): https://github.com/dotnet/corefx/pull/39001
شكرا جزيلا على ردودكم السريعةahsonkhan!
إن "تحديد" المفتاح باعتباره سلسلة منطقية بالفعل عندما أفكر في الأمر. أرى الآن أن Json.net تقوم بالفعل بإنشاء json مع كون المفتاح عبارة عن سلسلة ، عند إلغاء تسلسلها ستعيدني إلى Int. سيكون من الجيد بالتأكيد الحصول على دعم للمفاتيح غير الخيطية في المستقبل ، ولكن ليس سدادة العرض.
حسنًا ، سعيد لسماع أنه تم إصلاح خطأ Mvc.SerializableError غير المدعوم. هل لديك أي أفكار حول ما إذا كان هناك تاريخ مأمول لإصدار Preview 8؟ حاولت البحث والعثور على شيء ما ، ولكن لم أر شيئًا عن ذلك.
بمجرد إصدار المعاينة 8 ، سنحاول إعطاء مكتبة التسلسل .net core 3 json المحاولة مرة أخرى ، ولكن في الوقت الحالي نحتاج إلى التمسك بـ Json.net
steveharter ، layomia - هل هناك حل بديل محتمل هنا في هذه الأثناء؟ ما الذي يتطلبه الأمر لإضافة دعم لقاموس بدون سلسلة مفاتيح داخل المسلسل لـ 5.0؟
>
ahsonkhan @ willyt150 الحل لهذا هو استخدام محول مخصص يقوم بتنفيذ JsonConverter<T>
حيث T
هو Dictionary<int, string>
.
راجع https://github.com/dotnet/corefx/issues/36639#issue -429928740 للحصول على بعض الأمثلة.
هل لديك أي أفكار حول ما إذا كان هناك تاريخ مأمول لإصدار Preview 8؟
في وقت لاحق من هذا الشهر.
بالتفكير في هذا الأمر أكثر ، وإزالة الخيارات الجاهزة في الوقت الحالي نظرًا لأنه قد يكون شيئًا لا نريد دعمه افتراضيًا.
شكرًا لك layomia ، سألقي نظرة على ذلك.
شكرًا ahsonkhan ، أتطلع إلى الإصلاح القادم!
من namse (من https://github.com/dotnet/corefx/issues/40404):
أهلا. عندما أحاول إجراء تسلسل للقاموس باستخدام مفتاح عدد صحيح ، فإنه يرمي System.NotSupportedException.
أعتقد أنه من المنطقي دعم تسلسل Json الذي يحتوي على قاموس
ToString
مفتاح. على سبيل المثال ، عندما نقوم بتشغيل ToString لـ int أو boolean ، فإنها تُرجع "123" أو "true". أعتقد أن هذا المفتاح هوToString
مفتاح قابل.فيريسون
System.Text.Json Nuget الإصدار: 4.6.0-preview8.19405.3
الشفرة
var dictionary = new Dictionary<int, string> { [5] = "five" }; JsonSerializer.Serialize(dictionary);
متوقع
"{"5": "five"}"
لكن ماذا حدث
خطأ
System.NotSupportedException
إلقاؤهفي الواقع ، هناك مشكلة في التوافق عندما أقوم بتغيير Newtonsoft.Json إلى System.Text.Json. يعيدون السلسلة كما توقعت. أعتقد أنه ليس من الضروري أن يكون System.Text.Json متوافقًا ولكن ... كما تعلم.
لقد قمت بتطبيق محول يدعم كلاً من التسلسل وإلغاء التسلسل لـ IDictionary<TKey, TValue>
حيث يحتوي TKey
على طريقة ثابتة TKey Parse(string)
:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace JsonDictionaryConverter
{
sealed class JsonNonStringKeyDictionaryConverter<TKey, TValue> : JsonConverter<IDictionary<TKey, TValue>>
{
public override IDictionary<TKey, TValue> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var convertedType = typeof(Dictionary<,>)
.MakeGenericType(typeof(string), typeToConvert.GenericTypeArguments[1]);
var value = JsonSerializer.Deserialize(ref reader, convertedType, options);
var instance = (Dictionary<TKey, TValue>)Activator.CreateInstance(
typeToConvert,
BindingFlags.Instance | BindingFlags.Public,
null,
null,
CultureInfo.CurrentCulture);
var enumerator = (IEnumerator)convertedType.GetMethod("GetEnumerator")!.Invoke(value, null);
var parse = typeof(TKey).GetMethod("Parse", 0, BindingFlags.Public | BindingFlags.Static, null, CallingConventions.Any, new[] { typeof(string) }, null);
if (parse == null) throw new NotSupportedException($"{typeof(TKey)} as TKey in IDictionary<TKey, TValue> is not supported.");
while (enumerator.MoveNext())
{
var element = (KeyValuePair<string?, TValue>)enumerator.Current;
instance.Add((TKey)parse.Invoke(null, new[] { element.Key }), element.Value);
}
return instance;
}
public override void Write(Utf8JsonWriter writer, IDictionary<TKey, TValue> value, JsonSerializerOptions options)
{
var convertedDictionary = new Dictionary<string?, TValue>(value.Count);
foreach (var (k, v) in value) convertedDictionary[k?.ToString()] = v;
JsonSerializer.Serialize(writer, convertedDictionary, options);
convertedDictionary.Clear();
}
}
sealed class JsonNonStringKeyDictionaryConverterFactory : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
if (!typeToConvert.IsGenericType) return false;
if (typeToConvert.GenericTypeArguments[0] == typeof(string)) return false;
return typeToConvert.GetInterface("IDictionary") != null;
}
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
var converterType = typeof(JsonNonStringKeyDictionaryConverter<,>)
.MakeGenericType(typeToConvert.GenericTypeArguments[0], typeToConvert.GenericTypeArguments[1]);
var converter = (JsonConverter)Activator.CreateInstance(
converterType,
BindingFlags.Instance | BindingFlags.Public,
null,
null,
CultureInfo.CurrentCulture);
return converter;
}
}
}
اختبار:
class Entity
{
public string Value { get; set; }
}
class TestClass
{
public Dictionary<int, Entity> IntKey { get; set; }
public Dictionary<float, Entity> FloatKey { get; set; }
public Dictionary<double, Entity> DoubleKey { get; set; }
public Dictionary<DateTime, Entity> DateTimeKey { get; set; }
public Dictionary<string, Entity> StringKey { get; set; }
}
class Program
{
static void Main(string[] args)
{
var options = new JsonSerializerOptions();
options.Converters.Add(new JsonNonStringKeyDictionaryConverterFactory());
var x = new TestClass
{
IntKey = new Dictionary<int, Entity> { [1] = new Entity { Value = "test" } },
FloatKey = new Dictionary<float, Entity> { [1.3f] = new Entity { Value = "test" } },
DoubleKey = new Dictionary<double, Entity> { [1.35] = new Entity { Value = "test" } },
DateTimeKey = new Dictionary<DateTime, Entity> { [DateTime.Now] = new Entity { Value = "test" } },
StringKey = new Dictionary<string, Entity> { ["test"] = new Entity { Value = "test" } }
};
var value = JsonSerializer.Serialize(x, options);
Console.WriteLine(value);
var obj = JsonSerializer.Deserialize<TestClass>(value, options);
Console.WriteLine(JsonSerializer.Serialize(obj, options));
}
}
نتيجة:
{"IntKey":{"1":{"Value":"test"}},"FloatKey":{"1.3":{"Value":"test"}},"DoubleKey":{"1.35":{"Value":"test"}},"DateTimeKey":{"8/25/2019 6:47:48 PM":{"Value":"test"}},"StringKey":{"test":{"Value":"test"}}}
{"IntKey":{"1":{"Value":"test"}},"FloatKey":{"1.3":{"Value":"test"}},"DoubleKey":{"1.35":{"Value":"test"}},"DateTimeKey":{"8/25/2019 6:47:48 PM":{"Value":"test"}},"StringKey":{"test":{"Value":"test"}}}
ومع ذلك ، لا يزال يتعذر عليه إجراء تسلسل لقاموس متداخل مثل Dictionary<int, Dictionary<int, int>>
لأن System.Text.Json لا يقبل النوع الداخلي Dictionary<int, int>
. أعتقد أنه خطأ.
ومع ذلك ، لا يزال يتعذر إجراء تسلسل لقاموس متداخل مثل القاموس
> لأن System.Text.Json لا يقبل قاموس النوع الداخلي . أعتقد أنه خطأ.
دعم <string, x>
هو حسب التصميم بسبب تقليص النطاق من أجل الشحن لـ v3.0. الغرض من الإصدار 3.0 هو أن يكون منتجًا قابلاً للتطبيق مع دعم السيناريوهات الأكثر شيوعًا.
steveharter على الأقل ، لا يجب عليك طرح استثناء للدعم عندما يكون هناك محول صالح للاستخدام.
هل هناك أي خطط لدعم هذا في .net core 3.1؟
بالنسبة للوافدين الجدد ، فإن الحل المؤقت هو العودة إلى Newtonsoft.Json
.
Microsoft.AspNetCore.Mvc.NewtonsoftJson
..AddNewtonsoftJson()
بعد .AddControllers()
/ .AddMvc()
أو أي مجموعة أخرى.steveharter على الأقل ، لا يجب عليك طرح استثناء للدعم عندما يكون هناك محول صالح للاستخدام.
نعم هذه نقطة عادلة. ربما يمكننا إزالة هذا القيد لـ 3.1. cc playomia
أيضًا فقط لتوضيح أن عناصر القاموس اليوم متسلسلة مثل الخصائص وهو أمر ممكن لأن المفتاح عبارة عن سلسلة. دعم المفاتيح غير المتسلسلة يعني أنه سيتم إجراء تسلسل للعناصر على أنها KeyValuePair.
يا فتى ، واجهت هذه المشكلة بعد أن قمت بالترقية إلى 3.0.
اضطررت إلى تثبيت حزمة نيوتن مع AddNewtonsoftJson.
من israellot في https://github.com/dotnet/corefx/issues/41345
var dictionary = new Dictionary<int, int>() { [0] = 1 }; var serialized = System.Text.Json.JsonSerializer.Serialize(dictionary);
يتم التعامل مع هذا التسلسل البسيط بشكل جيد بواسطة مكتبة Newtonsoft json الافتراضية السابقة عن طريق إجراء تسلسل للمفتاح int كسلسلة. على System.Text.Json يطرح استثناء غير مدعوم.
israellot و unruledboy وغيرهما في سلسلة Dictionary<string, TValue>
لن ينجح؟ أرغب في رؤية بعض الاستخدامات لجمع المتطلبات وللمساعدة في تحفيز الإصلاح.
سيتم تسلسلها كسلاسل على أي حال ، لذلك لا أفهم السيناريوهات التي تريد أن يحتوي قاموسك الأساسي على مفاتيح int32 بدلاً من ذلك.
ahsonkhan أعتقد أن الدافع الرئيسي هو التوافق.
كان المُسلسل الافتراضي السابق هو Newtonsoft ، لذلك ربما كتب المستخدمون نماذج كاملة بالاعتماد على قدرته على إجراء تسلسل للفئات العشوائية وإلغاء تسلسلها. سيؤدي الترحيل من 2.X إلى 3.0 الآن إلى تغيير فاصل صامت لأننا سنعرف فقط عدم التوافق في وقت التشغيل.
أعتقد أن العديد من السيناريوهات تتضمن استخدام json تمامًا مثل النقل عبر السلك ، وفي هذه الحالة ، قد يكون نموذج المجال هو Dictionary
بالنظر بدقة إلى المسلسل ، فإن تقييد القاموس على وجود مفاتيح سلسلة أمر منطقي لأن هذا هو تمثيل json الوحيد الممكن. لكن بالنظر إلى أن المسلسل يلعب دورًا في التطبيقات ، أعتقد أنه من الأفضل إزالة أكبر قدر ممكن من الاحتكاك.
لقد واجهت هذه المشكلة مع برنامج صغير أكتبه حيث يتم توفير أجزاء من تسمية الإصدار من خلال ملف json.
تحتوي أجزاء الملصق على مفتاح يحدد الفهرس حيث يمكن إدراج جزء التسمية. هذا يعني أن المفاتيح عبارة عن قيم رقمية ، على سبيل المثال
{
"parts" : {
"1" : "alpha",
"3" : "beta"
}
}
باستخدام Newtonsoft ، يمكن إلغاء تسلسل json بدون إصدار إلى Dictionary<int, string>
. بعد التحويل إلى System.Text.Json فشل التسلسل.
لقد قمت بحل هذه المشكلة عن طريق إنشاء DictionaryConverter و DictionaryConverter الخاص بي
لقد قمت أيضًا بإنشاء محول بسيط يسمح بإلغاء تسلسل الأعداد الصحيحة من سلسلة
ثم يتم تسجيلها من خلال خيارات المسلسل: https://github.com/Kieranties/SimpleVersion/blob/master/src/SimpleVersion.Core/Serialization/Serializer.cs#L22
تسمح هذه التغييرات بإلغاء تسلسل مفاتيح القاموس بدلاً من قراءتها مباشرةً كسلسلة. يفتح هذا أيضًا الدعم للمفاتيح لتكون أنواعًا عشوائية يمكن أن يكون لها محولات خاصة بها مسجلة للتسلسل (على سبيل المثال ، التعداد / النوع / الأنواع التي يمكن تسلسلها كمفاتيح فريدة وما إلى ذلك)
لم أختبر الأشياء رسميًا ولكن في إطار التطوير الحالي يبدو أن هذا قد حل المشكلة.
تعيين معلم لـ 3.1 لإزالة أي قيود تمنع إنشاء محول مخصص يمكنه التعامل مع أي TKey
مقابل Dictionary<TKey,TValue>
.
تحديث: لقد أضفت عينات تعمل مع 3.0. لم ألاحظ أي مشكلات مثل القواميس المتداخلة كما هو مذكور أعلاه.
هناك نوعان من تنسيقات JSON المستخدمة في العينات:
{"1":"val1","2":"val2"}
بالرغم من أن TKey
ليس سلسلة.TryParse
على نوع المفتاح المدعوم المقابل. بالنسبة للإصدار 3.0 ، ليس من المجدي تقديم دعم معمم TKey
حيث أن طرق TryParse
يمكن أن تكون مختلفة عن أي TKey
ولأن هناك إعدادات ثقافية يجب توفيرها (عادة ثابت). لذا فإن العينات أدناه تخص نوعًا واحدًا من TKey
.Sample Dictionary<int, string>
. هذا مثال بسيط لمجرد TValue
== string
.Sample Dictionary<Guid, TValue>
. هذا يمكن أن يتعامل مع أي TValue
.Sample Dictionary<TKey, TValue> where TKey is Enum
. من أجل Enums هذا يمكن أن يتعامل مع أي TValue
.[{"Key":1,"Value":"val1"},{"Key":2,"Value":"val2"}]
Sample Dictionary<int, string>
. هذا مثال بسيط على TValue
== string
.Sample Dictionary<TKey, TValue>
. يمكن أن يتعامل هذا مع أي TKey
و TValue
لأن الأنواع ممثلة أصلاً في JSON ولا تتطلب TryParse
.إذا كانت هذه العينات مرضية ، فسوف أقوم بتغيير هذه المشكلة إلى 5.0 لمناقشة ما إذا كنا نقدم دعمًا مدمجًا لا يتطلب محولات مخصصة.
تعيين معلم إلى 5.0 للنظر فيه (ماذا لو كان أي من الأمثلة المذكورة أعلاه يجب أن يعمل بشكل افتراضي).
يبدو أيضًا أن إلغاء التسلسل يعين أنواع الكائنات العامة إلى JsonDocument بدلاً من الأنواع العادية (البدائية؟).
مثال:
string test = "[{\"id\":86,\"name\":\"test\"}]";
var SystemTextJson = System.Text.Json.JsonSerializer.Deserialize<List<Dictionary<string, object>>>(test);
var NewtonSoftJson = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(test);
يظهر SystemTextJson [0] ["id"] بالشكل: ValueKind = الرقم: "86"
يظهر NewtonSoftJson [0] ["id"] بالشكل: 86
steveharter يتسلسل قاموس تعداد
{
"Stuff": [
{
"Key": 1,
"Value": "String"
},
{
"Key": 3,
"Value": "String"
},
{
"Key": 2,
"Value": "String"
}
]
}
بينما تقدم JSON.NET ما أفترض أن معظم الناس يتوقعونه:
{
"Stuff": {
"Item1": "String",
"Item2": "String",
"Item3": "String"
}
يبدو أيضًا أن إلغاء التسلسل يعين أنواع الكائنات العامة إلى JsonDocument بدلاً من الأنواع العادية (البدائية؟).
نعم هذا حسب التصميم. راجع https://github.com/dotnet/corefx/issues/38713
steveharter يتسلسل قاموس تعداد
{"Stuff": [{"Key": 1، "Value": "String"}، {"Key": 3، "Value": "String"}، {"Key": 2، "Value": " سلسلة" } ] }
بينما تقدم JSON.NET ما أفترض أن معظم الناس يتوقعونه:
{"Stuff": {"Item1": "String"، "Item2": "String"، "Item3": "String"}
أفترض أنك تستخدم "نموذج القاموس
نعم ، هذا واحد. وآه حسنًا ، أعتقد أنك كنت تقصد ذلك كمسلسل عام للقاموس.
مهتم برؤية عينتك الجديدة عندما تكون متاحة ، لأن العينة التي نستخدمها حاليًا لا تبدو بالسرعة التي أريدها.
roguecode هنا نموذج Enum لـ Dictionary<TKey, TValue>
حيث TKey هو Enum ويستخدم صيغة JSON "الخاصية" بدلاً من KeyValuePair. لقد قمت أيضًا بتحديث قائمة العينات أعلاه لتشمل هذه العينة الجديدة.
مرحبًا ، لدي شيء مشابه ولكنه مختلف وأتساءل عما إذا كان يمكنك توجيهي إلى مكان آخر للبحث فيه.
نيوتن سوفت. Json: 12.0.2
Microsoft.AspNetCore.Mvc.NewtonsoftJson: 3.0.0
بدء التشغيل ك 3.0:
.AddMvc(mvcOptions => mvcOptions.EnableEndpointRouting = false)
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddNewtonsoftJson();
إذا كانت لدي هذه المشكلة تفاصيل الكائن:
// problemDetails has 2 extension items
{Microsoft.AspNetCore.Mvc.ValidationProblemDetails}
Detail: "Please refer to the 'errors' property for additional details."
Errors: Count = 1
Extensions: Count = 2
Instance: "/api/test/complex-binding-from-query"
Status: 400
Title: "One or more validation errors occurred."
Type: "https://tools.ietf.org/html/rfc7231#section-6.5.1"
في 2.2 ، تنفيذ عوائد Newtonsoft.Json.JsonConvert.SerializeObject(problemDetails)
{"errors":{"Int":["The value 'a' is not valid for Int."]},"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1","title":"One or more validation errors occurred.","status":400,"detail":"Please refer to the 'errors' property for additional details.","instance":"/api/test/complex-binding-from-query","traceId":"0HLQQ40AFBJNG","correlationId":"0HLQQ40AFBJNG"}
في 3.0 يعود:
{"Errors":{"param":["The value 'a' is not valid."]},"Type":"https://tools.ietf.org/html/rfc7231#section-6.5.1","Title":"One or more validation errors occurred.","Status":400,"Detail":"Please refer to the 'errors' property for additional details.","Instance":"/bad-request","Extensions":{"traceId":"|d0d40f80-48b6c9184401b0e1.","correlationId":"0HLQR10NSMRGD:00000009"}}
تتضمن السلسلة المتسلسلة للإصدار 3.0 IDictionaryExtensions
، ويمكننا إلغاء تسلسل هذه السلسلة بشكل صحيح في 3.0. يمكنك أن ترى أن اسم الخاصية هذا متروك من الإصدار 2.x.
المشكلة هي أن التسلسل 3.0 الذي يحدث عندما يتم إرجاع الاستجابة من عامل تصفية باستخدام BadRequestObjectResult
، من الكود أدناه:
public sealed class ProblemDetailsResultFilterAttribute : Attribute, IAlwaysRunResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
context.Result = new BadRequestObjectResult(problemDetails);
}
}
... ، محتوى الاستجابة الذي يتم إرجاعه هو نفس شكل الإصدار 2.2 (تم استبعاد اسم الخاصية Extensions
) ، مما يتسبب في إلغاء تسلسل الخاصية Extensions
كمجموعة فارغة (باستخدام Newtonsoft.Json.JsonConvert.DeserializeObject<ValidationProblemDetails>()
)
بطريقة ما ، لا يستخدم هذا التسلسل نفس التسلسل مثل مكتبة Newtonsoft التي نحاول إلغاء التسلسل معها.
شكرا للنظر!
لدي شيء مشابه لكن مختلف
@ ts46235 هل يمكنك من فضلك فتح إصدار جديد لهذا لأن هذا يختلف عن الإصدار الحالي؟
@ ts46235 لقد أجبت على سؤالك في الإصدار الآخر الذي فتحته هنا - https://github.com/aspnet/AspNetCore/issues/16618. جعل المحادثة هنا خارج الموضوع.
تم التحديث إلى Core 3.1 وما زال غير ثابت
لقد قمت بالترقية إلى 3.1 للتو وتعرضت لهذا. رجوع إلى JSON.NET أذهب ... (أستخدم مفاتيح GUID)
دوت نت كور 3.1.2
قاموس
أنا أيضًا أصبت بهذا ، ويا له من قيود صامتة مخيفة ، حيث أشار آخرون إلى أنك لن ترى هذا في وقت الترجمة. في حالتي ، أريد إجراء تسلسل لـ Dictionary<int, List<string>>
، والذي لا يبدو لي غريبًا بشكل خاص.
يجب أن يصلحوه ولكني أرى هذا مرارًا وتكرارًا حتى مع المنسق القديم ، والمنسق الثنائي في وقت مبكر newtsoft ، والقواميس في القواميس ، والقواميس ذات الواجهات. يجب عليهم إصلاحها ، ولكن إذا كنت لا تريد المشاكل ، فلا يجب على الأشخاص حقًا وضع أشياء معقدة مثل القواميس في عقود التسلسل ، حيث يطلبون منك مشكلة - لقد أفسد موقع newtsoft الأشخاص. انظر إلى جميع الخصائص العامة في Dictionary count وما إلى ذلك ، فأنت تعتمد على شيء مخصص في المسلسل لتعيين ذلك.
لسوء الحظ ، لا يوجد نوع بسيط لهذا في C # لأسماء الخصائص ، لذلك يتم فرض القاموس. لذلك انا حزين فقط ..
إليك حل بديل ولكنه ليس حلاً كاملاً بأي حال من الأحوال:
[JsonConverter(typeof(DictionaryConverter))]
public Dictionary<string, object> ExtraProperties { get; set; } = new Dictionary<string, object>();
public class DictionaryConverter : JsonConverter<Dictionary<string, object>>
{
public override Dictionary<string, object> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var dictionary = JsonSerializer.Deserialize<Dictionary<string, object>>(ref reader, options);
foreach (string key in dictionary.Keys.ToList())
{
if (dictionary[key] is JsonElement je)
{
dictionary[key] = Unwrap(je);
}
}
return dictionary;
}
public override void Write(Utf8JsonWriter writer, Dictionary<string, object> value, JsonSerializerOptions options)
=> JsonSerializer.Serialize(writer, value, options);
private static object Unwrap(JsonElement je)
{
return je.ValueKind switch
{
JsonValueKind.String => je.ToString(),
JsonValueKind.Number => je.TryGetInt64(out var l) ? l : je.GetDouble(),
JsonValueKind.True => true,
JsonValueKind.False => false,
JsonValueKind.Array => je.EnumerateArray().Select(Unwrap).ToList(),
JsonValueKind.Object => je.EnumerateObject().ToDictionary(x => x.Name, x => Unwrap(x.Value)),
_ => null
};
}
ربما يمكن إضافة دعم (بعض) الأنواع الشائعة للمسلسلات OOTB ، على سبيل المثال هذه القائمة ، وأيضًا إذا كان أحد هذه الأنواع .IsAssignableFrom(systemDotObjectInstance.GetType())
لدعم Dictionary<<ins i="7">object</ins>, V>
.
إليك اقتراح إضافة دعم لأنواع غير سلسلة TKey
في القواميس.
https://github.com/dotnet/runtime/pull/32676
من فضلك دعنا نعرف أي أفكار أو مخاوف.
على وجه التحديد ، يرجى تقديم ملاحظات حول مجموعة الأنواع التي تخطط Jozkee لدعم مفاتيح القاموس ، خاصة إذا كنت بحاجة إلى دعم أنواع أخرى (بشكل أساسي ، جميع الأنواع الرقمية الأولية المضمنة ، والتعدادات ، وعدد قليل من الأنواع الأخرى):
https://github.com/dotnet/runtime/blob/a5d96c0e280b56412d4614848f5ee3b1e0d7f216/src/libraries/System.Text.Json/docs/KeyConverter_spec.md#keyconverter
قاموس
@ andrew-vdb ، دعم تسلسل مفاتيح الكائنات العشوائية سيظل على الأرجح غير مدعوم. ومع ذلك ، إذا كان نوع وقت تشغيل مفاتيح الكائن أحد أنواع "المدعومة حديثًا" ، فسيعمل التسلسل لذلك بمجرد الانتهاء من الميزة. ومع ذلك ، سيظل إلغاء التسلسل على شكل JsonElement (حتى تتم معالجة هذه المشكلة المتعلقة بالاشتراك في السلوك المختلف): https://github.com/dotnet/runtime/issues/29960
Jozkee ما هي الأنواع الممكنة لـ TValue
؟ من المفترض أن أي شيء يمكنك إجراء تسلسل له حاليًا ككائن مستقل؟
من المفترض أن أي شيء يمكنك إجراء تسلسل له حاليًا ككائن مستقل؟
نعم فعلا.
https://docs.microsoft.com/en-gb/dotnet/standard/serialization/system-text-json-converters-how-to#support -dictionary-with-non-string-key
يبدو أيضًا أن إلغاء التسلسل يعين أنواع الكائنات العامة إلى JsonDocument بدلاً من الأنواع العادية (البدائية؟).
مثال:
string test = "[{\"id\":86,\"name\":\"test\"}]"; var SystemTextJson = System.Text.Json.JsonSerializer.Deserialize<List<Dictionary<string, object>>>(test); var NewtonSoftJson = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(test);
يظهر SystemTextJson [0] ["id"] بالشكل: ValueKind = الرقم: "86"
يظهر NewtonSoftJson [0] ["id"] بالشكل: 86
من بين جميع القضايا المذكورة ، هذا يزعجني أكثر. قائمة
الغرض من الإصدار 3.0 هو أن يكون منتجًا قابلاً للتطبيق مع دعم السيناريوهات الأكثر شيوعًا
أتساءل كيف القائمة
[// N objects
{"a":4},
{"b","Bla"},
]
نظرًا لأن هذا يؤدي أيضًا إلى إلغاء التسلسل إلى System.Text.JsonElement ، حيث أتوقع مضاعفة (رقم) وسلسلة (سلسلة)
لقد واجهت هذه المشكلة مع برنامج صغير أكتبه حيث يتم توفير أجزاء من تسمية الإصدار من خلال ملف json.
تحتوي أجزاء الملصق على مفتاح يحدد الفهرس حيث يمكن إدراج جزء التسمية. هذا يعني أن المفاتيح عبارة عن قيم رقمية ، على سبيل المثال{ "parts" : { "1" : "alpha", "3" : "beta" } }
باستخدام Newtonsoft ، يمكن إلغاء تسلسل json بدون إصدار إلى
Dictionary<int, string>
. بعد التحويل إلى System.Text.Json فشل التسلسل.لقد قمت بحل هذه المشكلة عن طريق إنشاء DictionaryConverter و DictionaryConverter الخاص بي
.
لقد قمت أيضًا بإنشاء محول بسيط يسمح بإلغاء تسلسل الأعداد الصحيحة من سلسلةثم يتم تسجيلها من خلال خيارات المسلسل: https://github.com/Kieranties/SimpleVersion/blob/feature/netcore3/src/SimpleVersion.Core/Serialization/Serializer.cs#L20
تسمح هذه التغييرات بإلغاء تسلسل مفاتيح القاموس بدلاً من قراءتها مباشرةً كسلسلة. يفتح هذا أيضًا الدعم للمفاتيح لتكون أنواعًا عشوائية يمكن أن يكون لها محولات خاصة بها مسجلة للتسلسل (على سبيل المثال ، التعداد / النوع / الأنواع التي يمكن تسلسلها كمفاتيح فريدة وما إلى ذلك)
لم أختبر الأشياء رسميًا ولكن في إطار التطوير الحالي يبدو أن هذا قد حل المشكلة.
مرحبا Kieranties ، روابط جيثب 404 بالنسبة لي
مرحبا Kieranties ، روابط جيثب 404 بالنسبة لي
AirEssY لقد صححت الروابط في تعليقي الأصلي ، أعتقد أنها الآن في إتقان على: https://github.com/Kieranties/SimpleVersion/tree/master/src/SimpleVersion.Core/Serialization
إذا كان القاموس مكافئًا لخريطة JavaScript ، فيجب أن يكون أي نوع (JS ممثل في C #) مقبولًا ،
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
A Map's keys can be any value (including functions, objects, or any primitive).
مثال على النهج القياسي لإلغاء تسلسل خريطة في JS هو:
const countries = new Map(JSON.parse('[[1,"Bahamas (the)"],[2,"Bolivia (Plurinational State of)"]]'))
console.log(countries)
والتي تنتج:
Map(2) {
1 => 'Bahamas (the)',
2 => 'Bolivia (Plurinational State of)'
}
TL ؛ DR: تقييد المفاتيح بالأوتار لا يعمل بشكل جيد مع JS
Jozkee فهل هذا يأتي في .NET 5 فقط أم أنه سينتقل إلى 3. *؟
onionhammer .NET 5.0 ، يمكنك أيضًا تجربة الميزة في المعاينة التالية (5.0 معاينة 8).
لا توجد خطط لتحويل هذا إلى 3.x.
حل لـ asp net core 3.x:
var dic1 = new Dictionary<TKey, TValue>();
return Json(new { dic1 }); // does not work
var dic2 = from i in new Dictionary<TKey, TValue>() select new { i.Key, i.Value }
return Json(new { dic2 }); //works prety well
verloka هذا ليس الناتج المطلوب
Jozkee فهل هذا يأتي في .NET 5 فقط أم أنه سينتقل إلى 3. *؟
لن يتم نقل هذا إلى الإصدار 3.x ولكن يمكنك إضافة استخدام حزمة System.Text.Json NuGet في مشروعك للحصول على جميع الميزات الجديدة في .NET 5.
التعليق الأكثر فائدة
بالنسبة للوافدين الجدد ، فإن الحل المؤقت هو العودة إلى
Newtonsoft.Json
.Microsoft.AspNetCore.Mvc.NewtonsoftJson
..AddNewtonsoftJson()
بعد.AddControllers()
/.AddMvc()
أو أي مجموعة أخرى.