用枚举数组反序列化json [英] deserialize json with array of enum
问题描述
使用枚举:
namespace AppGlobals
{
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum BoardSymbols
{
[EnumMember(Value = "X")]
First = 'X',
[EnumMember(Value = "O")]
Second = 'O',
[EnumMember(Value = "?")]
EMPTY = '?'
}
}
我想为我的api定义一个模型:
I would like to define a model for my api:
using System;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Newtonsoft.Json;
namespace Assignment_1
{
public class MyRequest
{
//...
[Required]
[MinLength(9)]
[MaxLength(9)]
[JsonProperty("changeTypes", ItemConverterType = typeof(JsonStringEnumConverter))]
public AppGlobals.BoardSymbols[] GameBoard { get; set; }
}
}
GameBoard
应该以字符串数组的形式序列化为JSON,该字符串的名称由EnumMember
属性指定.此方法改编自将json字符反序列化为枚举.但是,它不起作用.如果我将枚举更改为:
Where GameBoard
should serialize to JSON as an array of strings with names specified by the EnumMember
attributes. This approach is adapted from Deserialize json character as enumeration. However, it does not work. This does works if I change the enum to:
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum BoardSymbols
{
X='X',
Y='Y'
}
但是我显然在空"枚举上达到了极限.我该怎么办?
But I obviously hit a limit on the 'empty' enumeration. How can I do this?
我的启动中没有AddNewtonsoftJson()
,完全转换为Newtonsoft.现在,我的错误也许更具可执行性:
I did not have AddNewtonsoftJson()
in my startup, converting over fully to Newtonsoft. Now my error is perhaps more actionable:
System.InvalidCastException: Unable to cast object of type 'CustomJsonStringEnumConverter' to type 'Newtonsoft.Json.JsonConverter'.
at Newtonsoft.Json.Serialization.JsonTypeReflector.CreateJsonConverterInstance(Type converterType, Object[] args)
这很有意义,在此为我指定的解决方案指定了一个JsonConverterFactory.我只需要原始的JsonConverter用例代替.
This makes sense, the solution prescribed to me here specified a JsonConverterFactory .. I just need the raw JsonConverter for my use case instead.
推荐答案
TL/DR:您在这里有两个基本问题:
TL/DR: You have two basic problems here:
-
.NET Core 3.0+具有 Json.NET .两者都安装时,这很容易做到,因为它们共享某些类名,例如
JsonSerializer
和JsonConverter
.
.NET Core 3.0+ has a new built-in JSON serializer
System.Text.Json
, and you are mixing up attributes and classes between this new serializer and Json.NET. This is very easy to do when both are installed because they share some class names, such asJsonSerializer
andJsonConverter
.
默认情况下使用新的序列化器,但尚不支持将枚举序列化为具有自定义值名称的字符串;参见 System.Text.Json:如何为枚举值指定自定义名称? 有关详细信息.
The new serializer is used by default but does not yet support serialization of enums as strings with custom value names; see System.Text.Json: How do I specify a custom name for an enum value? for details.
解决问题的最简单方法是切换到Json.NET,如此处所示,并使用属性,转换器以及只能从此序列化程序获得的名称空间.
The easiest way to solve your problem is to switch back to Json.NET as shown here and use attributes, converters and namespaces exclusively from this serializer.
首先让我们分解两个序列化器之间的差异和相似之处:
First let's break down the differences and similarities between the two serializers:
-
System.Text.Json
:
-
自动内置到.NET Core 3.0+中,并由ASP.NET Core 3.0+用于JSON序列化命名空间
System.Text.Json
和System.Text.Json.Serialization
.Namespaces
System.Text.Json
andSystem.Text.Json.Serialization
.包括以下内容的类:
System.Text.Json.JsonSerializer
.Classes including
System.Text.Json.Serialization.JsonConverter
,System.Text.Json.Serialization.JsonConverter<T>
andSystem.Text.Json.JsonSerializer
.属性,包括
System.Text.Json.Serialization.JsonConverterAttribute
和System.Text.Json.Serialization.JsonExtensionDataAttribute
.Attributes including
System.Text.Json.Serialization.JsonPropertyNameAttribute
,System.Text.Json.Serialization.JsonConverterAttribute
andSystem.Text.Json.Serialization.JsonExtensionDataAttribute
.System.Text.Json.Serialization.JsonStringEnumConverter
,但是未实现通过属性重命名.请参见 ="a href =" https://stackoverflow.com/q/59059989的此答案. /3744182">System.Text.Json:如何为枚举值指定自定义名称? 以获得潜在的解决方法.
See this answer to System.Text.Json: How do I specify a custom name for an enum value? for potential workarounds.
Json.NET:
-
可通过在ASP.NET Core 3.0+中对Nuc进行序列化的第三方库,方法是将NuGet引用添加到
Microsoft.AspNetCore.Mvc.NewtonsoftJson
,然后调用有关详细信息,请参见此答案 /55666826/3744182> IMvcBuilder AddJsonOptions在.Net Core 3.0中的何处? 通过戳 >.For details see this answer to Where did IMvcBuilder AddJsonOptions go in .Net Core 3.0? by poke.
命名空间,包括
Newtonsoft.Json
,Newtonsoft.Json.Converters
,中的其他.Namespaces including
Newtonsoft.Json
,Newtonsoft.Json.Converters
,Newtonsoft.Json.Linq
andNewtonsoft.Json.Serialization
among others.包括以下内容的类:
Newtonsoft.Json.JsonConverter
,Newtonsoft.Json.JsonConverter<T>
和Classes including
Newtonsoft.Json.JsonConverter
,Newtonsoft.Json.JsonConverter<T>
andNewtonsoft.Json.JsonSerializer
属性,包括
Newtonsoft.Json.JsonPropertyAttribute
,Newtonsoft.Json.JsonConverterAttribute
和其他.EnumMemberAttribute
属性已应用.Serialization of enums as renamed strings is supported automatically by
Newtonsoft.Json.Converters.StringEnumConverter
when theEnumMemberAttribute
attribute is applied.考虑到这一点,您在代码中使用哪个序列化程序?由于您在问题中有用地包含了名称空间,因此我们可以检查:
With this in mind, which serializer are you using in your code? Since you helpfully included the namespaces in your question, we can check:
using System.Text.Json.Serialization; // System.Text.Json using Newtonsoft.Json; // Json.NET namespace Assignment_1 { public class MyRequest { //... [JsonProperty( // JsonProperty from Newtonsoft "changeTypes", ItemConverterType = typeof(JsonStringEnumConverter)// JsonStringEnumConverter from System.Text.Json )] public AppGlobals.BoardSymbols[] GameBoard { get; set; } } }
因此,如您所见,您正在将Newtonsoft的属性与
System.Text.Json
的转换器混合使用,这是行不通的. (也许您是在Visual Studio中从解析->使用..."中选择名称空间的?)So as you can see, you are mixing up attributes from Newtonsoft with converters from
System.Text.Json
, which isn't going to work. (Perhaps you selected the namespaces from a "Resolve -> using ..." right-click in Visual Studio?)那么,如何解决问题呢?由于Json.NET支持开箱即用地重命名枚举值,因此解决问题的最简单方法是使用此序列化器.尽管性能可能不如
System.Text.Json
,但它更完整,功能更全.So, how to resolve the problem? Since Json.NET supports renaming of enum values out of the box, the easiest way to resolve your problem is to use this serializer. While possibly not as performant as
System.Text.Json
it is much more complete and full-featured.为此,请删除命名空间
System.Text.Json.Serialization
和System.Text.Json
以及从代码中引用类型JsonStringEnumConverter
的引用,并按如下所示修改MyRequest
和BoardSymbols
:>To do this, remove the namespaces
System.Text.Json.Serialization
andSystem.Text.Json
and references to the typeJsonStringEnumConverter
from your code, and modifyMyRequest
andBoardSymbols
as follows:using System.Runtime.Serialization; using Newtonsoft.Json.Converters; using Newtonsoft.Json; namespace Assignment_1 { public class MyRequest { //... [Required] [MinLength(9)] [MaxLength(9)] [JsonProperty("changeTypes")] // No need to add StringEnumConverter here since it's already applied to the enum itself public AppGlobals.BoardSymbols[] GameBoard { get; set; } } } namespace AppGlobals { [JsonConverter(typeof(StringEnumConverter))] public enum BoardSymbols { [EnumMember(Value = "X")] First = 'X', [EnumMember(Value = "O")] Second = 'O', [EnumMember(Value = "?")] EMPTY = '?' } }
然后使用NuGet
Microsoft.AspNetCore.Mvc.NewtonsoftJson
和Startup.ConfigureServices
呼叫AddNewtonsoftJson()
:Then NuGet
Microsoft.AspNetCore.Mvc.NewtonsoftJson
and inStartup.ConfigureServices
callAddNewtonsoftJson()
:services.AddMvc() .AddNewtonsoftJson();
或者如果您希望全局使用
StringEnumConverter
:Or if you prefer to use
StringEnumConverter
globally:services.AddMvc() .AddNewtonsoftJson(o => o.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()));
请注意
注意:如果
AddNewtonsoftJson
方法不可用,请确保已安装 Newtonsoft.Json 软件包而不是 Microsoft.AspNetCore.Mvc.NewtonsoftJson 软件包.Note: If the
AddNewtonsoftJson
method isn't available, make sure that you installed the Microsoft.AspNetCore.Mvc.NewtonsoftJson package. A common error is to install the Newtonsoft.Json package instead of the Microsoft.AspNetCore.Mvc.NewtonsoftJson package.样机小提琴此处.
这篇关于用枚举数组反序列化json的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
-