Runtime: μƒˆλ‘œμš΄ Asp.NET Core 3.0 Json은 사전을 μ§λ ¬ν™”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.<key/>

에 λ§Œλ“  2019λ…„ 08μ›” 07일  Β·  51μ½”λ©˜νŠΈ  Β·  좜처: dotnet/runtime

.NET Core 3.0 미리 보기 7

Asp.NET Web APIλŠ” 사전을 λ°˜ν™˜ν•  λ•Œ 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, μœ ν˜• parentType, MemberInfo memberInfo, JsonSerializerOptions μ˜΅μ…˜)
at System.Text.Json.JsonClassInfo.CreateProperty(Type μ„ μ–ΈλœPropertyType, μœ ν˜• runtimePropertyType, PropertyInfo propertyInfo, μœ ν˜• parentClassType, JsonSerializerOptions μ˜΅μ…˜)
System.Text.Json.JsonClassInfo.AddPropertyμ—μ„œ(μœ ν˜• propertyType, PropertyInfo propertyInfo, μœ ν˜• classType, JsonSerializerOptions μ˜΅μ…˜)
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 μ˜΅μ…˜)
at System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, 개체 κ°’, μœ ν˜• μœ ν˜•, JsonSerializerOptions μ˜΅μ…˜, CancellationToken μ·¨μ†Œ 토큰)
Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext μ»¨ν…μŠ€νŠΈ, Encoding selectedEncoding)
Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext μ»¨ν…μŠ€νŠΈ, Encoding selectedEncoding)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvokerμ—μ„œ.g__Logged|21_0(ResourceInvoker 호좜자, IActionResult κ²°κ³Ό)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvokerμ—μ„œ.g__Awaited|29_0 TFilter,TFilterAsync
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μ—μ„œ.g__Awaited|19_0(ResourceInvoker 호좜자, μž‘μ—… lastTask, λ‹€μŒ μƒνƒœ, λ²”μœ„ λ²”μœ„, 개체 μƒνƒœ, λΆ€μšΈ isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvokerμ—μ„œ.g__Logged|17_1(ResourceInvoker 호좜자)
Microsoft.AspNetCore.Routing.EndpointMiddlewareμ—μ„œ.g__AwaitRequestTask|6_0(μ—”λ“œν¬μΈνŠΈ μ—”λ“œν¬μΈνŠΈ, νƒœμŠ€ν¬ requestTask, ILogger 둜거)
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, μœ ν˜• parentType, MemberInfo memberInfo, JsonSerializerOptions μ˜΅μ…˜)
at System.Text.Json.JsonClassInfo.CreateProperty(Type μ„ μ–ΈλœPropertyType, μœ ν˜• runtimePropertyType, PropertyInfo propertyInfo, μœ ν˜• parentClassType, JsonSerializerOptions μ˜΅μ…˜)
System.Text.Json.JsonClassInfo.AddPropertyμ—μ„œ(μœ ν˜• propertyType, PropertyInfo propertyInfo, μœ ν˜• classType, JsonSerializerOptions μ˜΅μ…˜)
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 μ˜΅μ…˜)
at System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, 개체 κ°’, μœ ν˜• μœ ν˜•, JsonSerializerOptions μ˜΅μ…˜, CancellationToken μ·¨μ†Œ 토큰)
Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext μ»¨ν…μŠ€νŠΈ, Encoding selectedEncoding)
Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext μ»¨ν…μŠ€νŠΈ, Encoding selectedEncoding)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvokerμ—μ„œ.g__Logged|21_0(ResourceInvoker 호좜자, IActionResult κ²°κ³Ό)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvokerμ—μ„œ.g__Awaited|29_0 TFilter,TFilterAsync
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μ—μ„œ.g__Awaited|19_0(ResourceInvoker 호좜자, μž‘μ—… lastTask, λ‹€μŒ μƒνƒœ, λ²”μœ„ λ²”μœ„, 개체 μƒνƒœ, λΆ€μšΈ isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvokerμ—μ„œ.g__Logged|17_1(ResourceInvoker 호좜자)
Microsoft.AspNetCore.Routing.EndpointMiddlewareμ—μ„œ.g__AwaitRequestTask|6_0(μ—”λ“œν¬μΈνŠΈ μ—”λ“œν¬μΈνŠΈ, νƒœμŠ€ν¬ requestTask, ILogger 둜거)
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 μ»¨ν…μŠ€νŠΈ)

area-System.Text.Json enhancement

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

μ‹ κ·œ 이민자의 경우 μž„μ‹œ 해결책은 Newtonsoft.Json 둜 λ˜λŒλ¦¬λŠ” κ²ƒμž…λ‹ˆλ‹€.

  1. Microsoft.AspNetCore.Mvc.NewtonsoftJson νŒ¨ν‚€μ§€ μ°Έμ‘°λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.
  2. .AddControllers() / .AddMvc() λ˜λŠ” λ‹€λ₯Έ μ‘°ν•© λ°”λ‘œ 뒀에 .AddNewtonsoftJson() μΆ”κ°€ν•©λ‹ˆλ‹€.

λͺ¨λ“  51 λŒ“κΈ€

"μ§€μ›λ˜μ§€ μ•ŠλŠ” μ˜ˆμ™Έ" 였λ₯˜λŠ” λͺ¨λ‘ κΈ°λ³Έ 제곡 직렬 λ³€ν™˜κΈ° λ‚΄μ˜ μ œν•œ 사항이며 μ˜λ„μ μœΌλ‘œ μ„€κ³„λœ κ²ƒμž…λ‹ˆλ‹€(적어도 3.0μ—μ„œ μ œκ³΅λ˜λŠ” 경우).

이 지원은 μ–Έμ œ μΆ”κ°€λ˜λ‚˜μš”? 이것은 Json.net 및 기타 직렬 λ³€ν™˜κΈ°μ—μ„œ μž μ‹œ λ™μ•ˆ μ§€μ›λ˜μ—ˆκΈ° λ•Œλ¬Έμ— 이것이 λ ˆμ΄λ”μ— 있기λ₯Ό λ°”λžλ‹ˆλ‹€.
Json.net을 λ‹€μ‹œ μ‚¬μš©ν•˜λ„λ‘ 선택할 수 μžˆλ‹€λŠ” 사싀에 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€. 이에 λŒ€ν•΄ λŒ€λ‹¨νžˆ κ°μ‚¬ν•©λ‹ˆλ‹€!

vNext(λ”°λΌμ„œ 5.0) μ΄μƒμ—μ„œ μ§€μ›ν•˜κΈ° μœ„ν•΄ 우리 λ ˆμ΄λ”μ— μžˆλŠ” 일련의 직렬 λ³€ν™˜κΈ° κΈ°λŠ₯이 있으며 μ‚¬μš©μž 지정 사전 지원이 κ·Έ 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€.

Asp.NET Web Apis, 사전을 λ°˜ν™˜ν•  λ•Œ NotSupportedExceptionκ³Ό ν•¨κ»˜ μ‹€νŒ¨ν•©λ‹ˆλ‹€.

직렬화할 λ•Œ ν˜„μž¬ Dictionary<string, TValue> 만 μ§€μ›λ©λ‹ˆλ‹€(즉, λ¬Έμžμ—΄μΈ TKey). κ·€ν•˜μ˜ 사전은 μ§€μ›λ˜μ§€ μ•ŠλŠ” <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μ—μ„œ):

μ•ˆλ…•ν•˜μ„Έμš”. μ •μˆ˜ ν‚€λ‘œ Dictionaryλ₯Ό μ§λ ¬ν™”ν•˜λ €κ³ ν•˜λ©΄ System.NotSupportedException이 λ°œμƒν•©λ‹ˆλ‹€.

Dictionary에 ToString -able ν‚€κ°€ μžˆλŠ” Json 직렬화λ₯Ό μ§€μ›ν•˜λŠ” 것이 합리적이라고 μƒκ°ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, int λ˜λŠ” boolean에 λŒ€ν•΄ ToString을 μ‹€ν–‰ν•˜λ©΄ "123" λ˜λŠ” "true"κ°€ λ°˜ν™˜λ©λ‹ˆλ‹€. λ‚˜λŠ” κ·Έ ν‚€κ°€ ToString -able 킀라고 μƒκ°ν•©λ‹ˆλ‹€.

Verison

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"}}}

κ·ΈλŸ¬λ‚˜ System.Text.Json이 λ‚΄λΆ€ μœ ν˜• Dictionary<int, int> ν—ˆμš©ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— Dictionary<int, Dictionary<int, int>> 와 같은 쀑첩 사전을 직렬화할 수 μ—†μŠ΅λ‹ˆλ‹€. 버그라고 μƒκ°ν•©λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ μ—¬μ „νžˆ Dictionary와 같은 쀑첩 사전을 직렬화할 수 μ—†μŠ΅λ‹ˆλ‹€.> System.Text.Json은 λ‚΄λΆ€ μœ ν˜• 사전을 ν—ˆμš©ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ—. 버그라고 μƒκ°ν•©λ‹ˆλ‹€.

<string, x> 만 μ§€μ›ν•˜λŠ” 것은 v3.0용으둜 μ œκ³΅ν•˜κΈ° μœ„ν•œ λ²”μœ„ μΆ•μ†Œλ‘œ 인해 μ˜λ„μ μœΌλ‘œ μ„€κ³„λœ κ²ƒμž…λ‹ˆλ‹€. 3.0 λ¦΄λ¦¬μŠ€λŠ” κ°€μž₯ 일반적인 μ‹œλ‚˜λ¦¬μ˜€κ°€ μ§€μ›λ˜λŠ” μ΅œμ†Œν•œμ˜ μ‹€ν–‰ κ°€λŠ₯ν•œ μ œν’ˆμž…λ‹ˆλ‹€.

@steveharter 적어도 μ‚¬μš© κ°€λŠ₯ν•œ λ³€ν™˜κΈ°κ°€ μžˆμ„ λ•Œ

.net core 3.1μ—μ„œ 이λ₯Ό 지원할 κ³„νšμ΄ μžˆμŠ΅λ‹ˆκΉŒ?

μ‹ κ·œ 이민자의 경우 μž„μ‹œ 해결책은 Newtonsoft.Json 둜 λ˜λŒλ¦¬λŠ” κ²ƒμž…λ‹ˆλ‹€.

  1. Microsoft.AspNetCore.Mvc.NewtonsoftJson νŒ¨ν‚€μ§€ μ°Έμ‘°λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.
  2. .AddControllers() / .AddMvc() λ˜λŠ” λ‹€λ₯Έ μ‘°ν•© λ°”λ‘œ 뒀에 .AddNewtonsoftJson() μΆ”κ°€ν•©λ‹ˆλ‹€.

@steveharter 적어도 μ‚¬μš© κ°€λŠ₯ν•œ λ³€ν™˜κΈ°κ°€ μžˆμ„ λ•Œ

예, 그것은 μ •λ‹Ήν•œ μ§€μ μž…λ‹ˆλ‹€. μ•„λ§ˆλ„ μš°λ¦¬λŠ” 3.1μ—μ„œ 이 μ œν•œμ„ μ œκ±°ν•  수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. cc @layomia

λ˜ν•œ μ˜€λŠ˜λ‚  사전 μš”μ†ŒλŠ” ν‚€κ°€ λ¬Έμžμ—΄μ΄κΈ° λ•Œλ¬Έμ— κ°€λŠ₯ν•œ μ†μ„±μ²˜λŸΌ μ§λ ¬ν™”λœλ‹€λŠ” 점을 λͺ…ν™•νžˆ ν•˜κΈ° μœ„ν•΄μ„œμž…λ‹ˆλ‹€. λ¬Έμžμ—΄μ΄ μ•„λ‹Œ ν‚€λ₯Ό μ§€μ›ν•˜λ©΄ μš”μ†Œκ°€ KeyValuePair둜 μ§λ ¬ν™”λ©λ‹ˆλ‹€.

이런, 3.0으둜 μ—…κ·Έλ ˆμ΄λ“œν•œ 직후에 이 λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.

AddNewtonsoftJson으둜 newton νŒ¨ν‚€μ§€λ₯Ό μ„€μΉ˜ν•΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€.

https://github.com/dotnet/corefx/issues/41345의 @israellot μ—μ„œ

var dictionary = new Dictionary<int, int>()
            {
                [0] = 1
            };

 var serialized = System.Text.Json.JsonSerializer.Serialize(dictionary);

이 κ°„λ‹¨ν•œ μ§λ ¬ν™”λŠ” int ν‚€λ₯Ό λ¬Έμžμ—΄λ‘œ μ§λ ¬ν™”ν•˜μ—¬ 이전 κΈ°λ³Έ Newtonsoft json λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ 잘 μ²˜λ¦¬λ©λ‹ˆλ‹€. System.Text.Jsonμ—μ„œ μ§€μ›λ˜μ§€ μ•ŠλŠ” μ˜ˆμ™Έκ°€ λ°œμƒν•©λ‹ˆλ‹€.

@israellot , @unruledboy 및 기타 μŠ€λ ˆλ“œμ˜ 경우 μ‹œλ‚˜λ¦¬μ˜€μ—μ„œ 개체 λͺ¨λΈμ— μ •μˆ˜ ν‚€κ°€ μžˆλŠ” 사전이 ν•„μš”ν•œ μ΄μœ μ™€ 이λ₯Ό Dictionary<string, TValue> λ³€κ²½ν•˜λ©΄ μž‘λ™ν•˜μ§€ μ•ŠλŠ” μ΄μœ μ— λŒ€ν•œ μ„ΈλΆ€ 정보λ₯Ό μ œκ³΅ν•  수 μžˆμŠ΅λ‹ˆκΉŒ? μš”κ΅¬ 사항을 μˆ˜μ§‘ν•˜κ³  μˆ˜μ • 사항에 동기λ₯Ό λΆ€μ—¬ν•˜λŠ” 데 도움이 λ˜λŠ” λͺ‡ 가지 μ‚¬μš©λ²•μ„ 보고 μ‹ΆμŠ΅λ‹ˆλ‹€.

μ–΄μ¨Œλ“  λ¬Έμžμ—΄λ‘œ μ§λ ¬ν™”λ˜λ―€λ‘œ κΈ°λ³Έ 사전에 λŒ€μ‹  int32 ν‚€λ₯Ό μ‚¬μš©ν•˜λ €λŠ” μ‹œλ‚˜λ¦¬μ˜€λ₯Ό 이해할 수 μ—†μŠ΅λ‹ˆλ‹€.

@ahsonkhan 핡심 λ™κΈ°λŠ” ν˜Έν™˜μ„±μ΄λΌκ³  μƒκ°ν•©λ‹ˆλ‹€.
이전 κΈ°λ³Έ 직렬 λ³€ν™˜κΈ°λŠ” Newtonsoftμ˜€μœΌλ―€λ‘œ μ‚¬μš©μžλŠ” μž„μ˜ 클래슀λ₯Ό 직렬화 및 μ—­μ§λ ¬ν™”ν•˜λŠ” κΈ°λŠ₯에 μ˜μ‘΄ν•˜μ—¬ 전체 λͺ¨λΈμ„ μž‘μ„±ν–ˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. 2.Xμ—μ„œ 3.0으둜 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ν•˜λ©΄ λŸ°νƒ€μž„ μ‹œ λΉ„ν˜Έν™˜μ„±λ§Œ μ•Œ 수 μžˆμœΌλ―€λ‘œ 이제 μ‘°μš©ν•œ μ£Όμš” λ³€κ²½ 사항이 λ°œμƒν•©λ‹ˆλ‹€.

λ§Žμ€ μ‹œλ‚˜λ¦¬μ˜€κ°€ μœ μ„ μ„ ν†΅ν•œ μ „μ†‘μœΌλ‘œ json을 μ‚¬μš©ν•˜λŠ” 것과 관련이 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. 이 경우 도메인 λͺ¨λΈμ€ 사전일 수 μžˆμŠ΅λ‹ˆλ‹€.. κ·€ν•˜μ˜ μ œμ•ˆμ€ λ³„λ„μ˜ DTO 객체 사전을 λ§Œλ“œλŠ” κ²ƒμœΌλ‘œ μš”μ•½λ©λ‹ˆλ‹€.그리고 λ‘˜ μ‚¬μ΄μ˜ λ³€ν™˜μ€ 직렬 λ³€ν™˜κΈ°μ™€ ν˜Έν™˜λ˜λ„λ‘ λ‹€λ₯Έ 개체λ₯Ό ν• λ‹Ήν•΄μ•Ό ν•˜λ―€λ‘œ λ‹€μ†Œ λΉ„νš¨μœ¨μ μž…λ‹ˆλ‹€.
직렬 λ³€ν™˜κΈ°λ₯Ό μ—„κ²©νžˆ μ‚΄νŽ΄λ³΄λ©΄ 사전에 λ¬Έμžμ—΄ ν‚€λ₯Ό μ‚¬μš©ν•˜λ„λ‘ μ œν•œν•˜λŠ” 것은 κ°€λŠ₯ν•œ μœ μΌν•œ 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

μ΄λŸ¬ν•œ 변경을 톡해 μ‚¬μ „μ˜ ν‚€λ₯Ό λ¬Έμžμ—΄λ‘œ 직접 μ½λŠ” λŒ€μ‹  역직렬화할 수 μžˆμŠ΅λ‹ˆλ‹€. 이것은 직렬화λ₯Ό μœ„ν•΄ λ“±λ‘λœ 자체 λ³€ν™˜κΈ°λ₯Ό κ°€μ§ˆ 수 μžˆλŠ” μž„μ˜ μœ ν˜•(예: 고유 ν‚€λ‘œ 직렬화될 수 μžˆλŠ” μ—΄κ±°ν˜•/μœ ν˜•/μœ ν˜• λ“±)이 될 킀에 λŒ€ν•œ 지원을 μΆ”κ°€λ‘œ μ—½λ‹ˆλ‹€.

κ³΅μ‹μ μœΌλ‘œ ν…ŒμŠ€νŠΈν•˜μ§€λŠ” μ•Šμ•˜μ§€λ§Œ ν˜„μž¬ 개발 λ‚΄μ—μ„œ 이것이 문제λ₯Ό ν•΄κ²°ν•œ 것 κ°™μŠ΅λ‹ˆλ‹€.

TKey λŒ€ν•œ Dictionary<TKey,TValue> TKey λ₯Ό μ²˜λ¦¬ν•  수 μžˆλŠ” μ‚¬μš©μž 지정 λ³€ν™˜κΈ°κ°€ μƒμ„±λ˜μ§€ μ•Šλ„λ‘ ν•˜λŠ” λͺ¨λ“  μ œν•œμ„ μ œκ±°ν•˜κΈ° μœ„ν•΄ 3.1에 λŒ€ν•œ λ§ˆμΌμŠ€ν†€μ„ μ„€μ •ν•©λ‹ˆλ‹€.

μ—…λ°μ΄νŠΈ: 3.0μ—μ„œ μž‘λ™ν•˜λŠ” μƒ˜ν”Œμ„ μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€. μœ„μ—μ„œ 보고된 쀑첩 사전과 같은 문제λ₯Ό λ°œκ²¬ν•˜μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.

μƒ˜ν”Œμ—λŠ” 두 가지 JSON ν˜•μ‹μ΄ μ‚¬μš©λ©λ‹ˆλ‹€.

  • λ¬Έμžμ—΄ 속성이 μžˆλŠ” JSON 객체: {"1":"val1","2":"val2"} TKey λŠ” λ¬Έμžμ—΄μ΄ μ•„λ‹ˆμ§€λ§Œ {"1":"val1","2":"val2"} μž…λ‹ˆλ‹€.

    • μ΄λŠ” μ§€μ›λ˜λŠ” ν•΄λ‹Ή ν‚€ μœ ν˜•μ˜ TryParse λ©”μ†Œλ“œμ— μ˜μ‘΄ν•©λ‹ˆλ‹€. v3.0의 경우 TryParse λ©”μ„œλ“œλŠ” TKey λŒ€ν•΄ λ‹€λ₯Ό 수 있고 μ œκ³΅ν•΄μ•Ό ν•˜λŠ” λ¬Έν™” 섀정이 있기 λ•Œλ¬Έμ— μΌλ°˜ν™”λœ TKey 에 λŒ€ν•œ 지원을 μ œκ³΅ν•˜λŠ” 것이 κ°€λŠ₯ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€ TryParse (일반적으둜 λΆˆλ³€). λ”°λΌμ„œ μ•„λž˜ μƒ˜ν”Œμ€ 단일 TKey μœ ν˜•μ— λŒ€ν•œ κ²ƒμž…λ‹ˆλ‹€.

    • Sample Dictionary<int, string> . 이것은 TValue == string λŒ€ν•œ κ°„λ‹¨ν•œ μ˜ˆμž…λ‹ˆλ‹€.

    • Sample Dictionary<Guid, TValue> . 이것은 λͺ¨λ“  TValue μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    • Sample Dictionary<TKey, TValue> where TKey is Enum . μ—΄κ±°ν˜•μ˜ 경우 이것은 λͺ¨λ“  TValue μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • KeyValuePair ν•­λͺ©μ΄ μžˆλŠ” JSON λ°°μ—΄: [{"Key":1,"Value":"val1"},{"Key":2,"Value":"val2"}]

    • Sample Dictionary<int, string> . 이것은 TValue == string λŒ€ν•œ κ°„λ‹¨ν•œ μ˜ˆμž…λ‹ˆλ‹€.

    • Sample Dictionary<TKey, TValue> . μœ ν˜•μ΄ 기본적으둜 JSON으둜 ν‘œμ‹œλ˜κ³  TryParse ν•„μš”ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 이것은 λͺ¨λ“  TKey 및 TValue λ₯Ό μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ΄λŸ¬ν•œ μƒ˜ν”Œμ΄ 만쑱슀러운 경우 μ‚¬μš©μž 지정 λ³€ν™˜κΈ°κ°€ ν•„μš”ν•˜μ§€ μ•Šμ€ κΈ°λ³Έ 제곡 지원을 μ œκ³΅ν•˜λŠ”μ§€ μ—¬λΆ€λ₯Ό λ…Όμ˜ν•˜κΈ° μœ„ν•΄ 이 문제λ₯Ό 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 = Number: "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 ν•΄λ‹Ή λ³€ν™˜κΈ°κ°€ μžˆλŠ” μ—΄κ±°ν˜• ν‚€ 사전은 λ‹€μŒκ³Ό 같이 μ§λ ¬ν™”λ©λ‹ˆλ‹€.
{ "λ‚΄μš©": [ { "ν‚€": 1, "κ°’": "λ¬Έμžμ—΄" }, { "ν‚€": 3, "κ°’": "λ¬Έμžμ—΄" }, { "ν‚€": 2, "κ°’": " 끈" } ] }
JSON.NET은 λŒ€λΆ€λΆ„μ˜ μ‚¬λžŒλ“€μ΄ μ˜ˆμƒν•  것이라고 κ°€μ •ν•˜λŠ” 것을 μ œκ³΅ν•˜μ§€λ§Œ:
{ "λ‚΄μš©": { "ν•­λͺ©1": "λ¬Έμžμ—΄", "ν•­λͺ©2": "λ¬Έμžμ—΄", "ν•­λͺ©3": "λ¬Έμžμ—΄" }

"μƒ˜ν”Œ 사전"을 μ‚¬μš©ν•˜κ³  μžˆλ‹€κ³  κ°€μ •ν•©λ‹ˆλ‹€."? κ·Έλ ‡λ‹€λ©΄ "Key" 및 "Value" 속성이 μžˆλŠ” KeyValuePairλ₯Ό μ‚¬μš©ν•œ κ²ƒμž…λ‹ˆλ‹€. 속성 μ΄λ¦„μœΌλ‘œ μ§λ ¬ν™”λ˜λŠ” TKey 기반 μ—΄κ±°ν˜• 사전에 λŒ€ν•œ μƒ˜ν”Œμ„ μ œκ³΅ν•˜μ§€ μ•Šμ•˜μ§€λ§Œ μΆ”κ°€ν•˜λŠ” μž‘μ—…μ„ ν•  κ²ƒμž…λ‹ˆλ‹€.

그래, κ·Έκ±°μ•Ό. 그리고 μ•„ μ’‹μ•„, λ‚˜λŠ” 당신이 그것을 일반 사전 직렬 λ³€ν™˜κΈ°λ‘œ μ˜λ―Έν•œλ‹€κ³  μƒκ°ν–ˆμŠ΅λ‹ˆλ‹€.
μš°λ¦¬κ°€ ν˜„μž¬ μ‚¬μš©ν•˜κ³  μžˆλŠ” μƒ˜ν”Œμ΄ λ‚΄κ°€ μ›ν•˜λŠ” κ²ƒλ§ŒνΌ λΉ λ₯΄μ§€ μ•Šμ€ 것 κ°™μ•„μ„œ μ‚¬μš© κ°€λŠ₯ν•œ 경우 μƒˆ μƒ˜ν”Œμ„ 보고 μ‹ΆμŠ΅λ‹ˆλ‹€.

@roguecode λ‹€μŒμ€ Dictionary<TKey, TValue> λŒ€ν•œ Enum μƒ˜ν”Œ μž…λ‹ˆλ‹€. μ—¬κΈ°μ„œ TKeyλŠ” Enum이고 KeyValuePair λŒ€μ‹  "속성" JSON ꡬ문을 μ‚¬μš©ν•©λ‹ˆλ‹€. λ˜ν•œ 이 μƒˆ μƒ˜ν”Œμ„ ν¬ν•¨ν•˜λ„λ‘ μœ„μ˜ μƒ˜ν”Œ λͺ©λ‘μ„ μ—…λ°μ΄νŠΈν–ˆμŠ΅λ‹ˆλ‹€.

μ•ˆλ…•ν•˜μ„Έμš”, λΉ„μŠ·ν•˜μ§€λ§Œ λ‹€λ₯Έ 것이 μžˆμŠ΅λ‹ˆλ‹€. λ‹€λ₯Έ 곳을 λ³Ό 수 μžˆλŠ”μ§€ μ•Œλ €μ£Όμ‹€ 수 μžˆλŠ”μ§€ κΆκΈˆν•©λ‹ˆλ‹€.

Newtonsoft.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 κ°œμ²΄κ°€ μžˆλŠ” 경우:

// 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 버전 직렬화 λ¬Έμžμ—΄μ—λŠ” IDictionaryκ°€ ν¬ν•¨λ©λ‹ˆλ‹€.속성 이름 Extensions 이며 3.0μ—μ„œ ν•΄λ‹Ή λ¬Έμžμ—΄μ„ μ˜¬λ°”λ₯΄κ²Œ 역직렬화할 수 μžˆμŠ΅λ‹ˆλ‹€. 이 속성 이름은 2.x λ²„μ „μ—μ„œ μ œμ™Έλœ 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

λ¬Έμ œλŠ” μ•„λž˜ μ½”λ“œμ—μ„œ BadRequestObjectResult μ‚¬μš©ν•˜μ—¬ ν•„ν„°μ—μ„œ 응닡이 λ°˜ν™˜λ  λ•Œ λ°œμƒν•˜λŠ” 3.0 μ§λ ¬ν™”μž…λ‹ˆλ‹€.

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
μ‚¬μ „λ˜ν•œ μž‘λ™ν•˜μ§€ μ•ŠμœΌλ©° ν‚€μ˜ κ°œμ²΄λ„ μ‹€μ œλ‘œ λ¬Έμžμ—΄μž…λ‹ˆλ‹€.

λ‚˜λ„ 방금 이것을 μ³€κ³  λ‹€λ₯Έ μ‚¬λžŒλ“€μ΄ μ§€μ ν–ˆλ“―μ΄ 컴파일 νƒ€μž„μ—λŠ” 이것을 λ³Ό 수 μ—†κΈ° λ•Œλ¬Έμ— λ¬΄μ„œμš΄ 침묡의 μ œν•œμž…λ‹ˆλ‹€. 제 κ²½μš°μ—λŠ” Dictionary<int, List<string>> λ₯Ό μ§λ ¬ν™”ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€. 이것은 νŠΉλ³„νžˆ 이ꡭ적이라고 μƒκ°ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

그듀은 그것을 고쳐야 ν•˜μ§€λ§Œ λ‚˜λŠ” μ˜ˆμ „ 포맷터, λ°”μ΄λ„ˆλ¦¬ 포맷터 early 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 λŒ€ν•΄ ν™œμ„±ν™”λœ μœ ν˜•μ€ λ¬΄μ—‡μž…λ‹ˆκΉŒ? μ•„λ§ˆλ„ ν˜„μž¬ 독립 μ‹€ν–‰ν˜• 개체둜 직렬화할 수 μžˆλŠ” 것은 λ¬΄μ—‡μž…λ‹ˆκΉŒ?

μ•„λ§ˆλ„ ν˜„μž¬ 독립 μ‹€ν–‰ν˜• 개체둜 직렬화할 수 μžˆλŠ” 것은 λ¬΄μ—‡μž…λ‹ˆκΉŒ?

예.

λ˜ν•œ μ—­μ§λ ¬ν™”λŠ” 일반 객체 μœ ν˜•μ„ 일반(κΈ°λ³Έ?) μœ ν˜•μ΄ μ•„λ‹Œ 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 = Number: "86"
NewtonSoftJson[0]["id"]λŠ” λ‹€μŒκ³Ό 같이 ν‘œμ‹œλ©λ‹ˆλ‹€. 86

μ–ΈκΈ‰λœ λͺ¨λ“  문제 μ€‘μ—μ„œ 이것이 λ‚˜λ₯Ό κ°€μž₯ κ΄΄λ‘­νžˆλŠ” λ¬Έμ œμž…λ‹ˆλ‹€. λͺ©λ‘λ˜λŠ” T[] λ˜λŠ” 사전Json이 가지고 μžˆλŠ” λͺ‡ 가지 μœ ν˜•μ—μ„œ CLR μœ ν˜•μœΌλ‘œ 직접 맀핑할 수 μžˆλŠ” λͺ¨λ“  μœ ν˜•μ— λŒ€ν•΄ μ μ ˆν•˜κ²Œ 역직렬화해야 ν•©λ‹ˆλ‹€.

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 , github 링크 404

μ•ˆλ…•ν•˜μ„Έμš” @Kieranties , github 링크 404

@AirEssY μ›λž˜ 의견의 링크λ₯Ό μˆ˜μ •ν–ˆμŠ΅λ‹ˆλ‹€. 이제 https://github.com/Kieranties/SimpleVersion/tree/master/src/SimpleVersion.Core/Serialization μ—μ„œ λ§ˆμŠ€ν„°μ— μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

사전이 JavaScript 맡과 λ™μΌν•˜λ©΄ λͺ¨λ“ (C#으둜 ν‘œν˜„λ˜λŠ” JS μœ ν˜•)이 ν—ˆμš©λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

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의 λͺ¨λ“  μƒˆλ‘œμš΄ κΈ°λŠ₯을 μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰