【问题标题】:How to deserialize json property for enumeration class using Json.Net?如何使用 Json.Net 反序列化枚举类的 json 属性?
【发布时间】:2020-07-06 18:28:46
【问题描述】:

我试图避免使用枚举,而是使用枚举类,例如此处https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/enumeration-classes-over-enum-types

现在我有下面的例子

public class Dto
{
public string Name {get;set;}
public StatusType Status {get;set;}
}

public class StatusType : Enumeration
{
public static readonly StatusType Active = new StatusType (1, "Active");
public static readonly StatusType Inactive = new StatusType (2, "Inactive");
}

当我尝试反序列化 Dto 时,例如

var message = JsonConvert.DeserializeObject<Dto>(test);

我收到一个错误“将值“Active”转换为“StatusType”时出错。

是否可以使用或创建一个转换器,将值“Active”实际转换为适当的 StatusType?

【问题讨论】:

  • Active 是静态只读字段
  • 这是一个问题还是一个陈述:)
  • 这是一个声明。你可以看到它是静态的。
  • 好吧,我想我们都可以看到它,这使得这种说法毫无用处。

标签: c# json.net


【解决方案1】:

您需要编写自定义JsonConverter。比如这样:

public class StatusTypeConverter : JsonConverter<StatusType>
{
    // can be build with reflection 
    private static Dictionary<string, StatusType> _map = new Dictionary<string, StatusType>(StringComparer.InvariantCultureIgnoreCase)
    {
        {StatusType.Active.Name, StatusType.Active},
        {StatusType.Inactive.Name, StatusType.Inactive}
    };
    public override void WriteJson(JsonWriter writer, StatusType value, JsonSerializer serializer)
    {
        writer.WriteValue(value.Name);
    }

    public override StatusType ReadJson(JsonReader reader, Type objectType, StatusType existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        string s = (string)reader.Value;

        return _map[s];
    }
}

public class Dto
{
    public string Name { get; set; }
    [JsonConverter(typeof(StatusTypeConverter))]
    public StatusType Status { get; set; }
}

var js = "{'name': 'Name', 'status': 'active'}";
Console.WriteLine(JsonConvert.DeserializeObject<Dto>(js).Status.Name); // prints "Active"

这段代码显然可以改进(缺少键的有意义的例外,构建可以处理Enumeration 的所有子类型的转换器)。

【讨论】:

  • 每当一个成员被添加到StatusType,就必须更新_map,这很愚蠢。
  • @Aybe 这是获得这个想法的示例代码。如果我要在生产中实现它,我会用反射构建字典。
  • @Aybe 我认为无需花费太多精力进行反射,就可以构建一个能够处理Enumeration 的所有子级的通用转换器。
  • @GuruStron 是的,我正在使用反射编写转换器,例如 var status = StatusType.GetAll().Where(a => a.Name == (string )reader.Value).FirstOrDefault();
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-15
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 2014-12-11
  • 2012-05-10
相关资源
最近更新 更多