JSON.Net显示枚举的名称和值对

lnvxswe2  于 2023-08-08  发布在  .NET
关注(0)|答案(2)|浏览(96)

这里有一个新手在C#中使用JSON.Net-

string JSONOutput = (JsonConvert.SerializeObject(product));

字符串
当我在我的解决方案中序列化Product对象时,我得到的JSON看起来像这样:

{
   "product":{
      "displayStatus":1,
      "drugClass":1,
      "drugType":1
   }
}


displayStatusdrugClassdrugType值都来自Enum s,所以我真正想要的输出是这样的:

{
   "product":{
      "displayStatus":{
         "name":"Visible",
         "value":1
      },
      "drugClass":{
         "name":"Generic",
         "value":1
      },
      "drugType":{
         "name":"Drug",
         "value":1
      }
   }
}


有人知道如何做到这一点吗?我一直在看StringEnumConverter,但我唯一能看到的是,它只是返回Enum的字符串,而不是整数值-而我希望两者都有。

ryevplcw

ryevplcw1#

您可以使用JsonConverter<T>,如下所示:

public class EnumConverter<T> : JsonConverter<T> where T : System.Enum
{
    public override T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer)
        => throw new NotImplementedException();

    public override void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer)
    {
        var nameAndValue = new { Name = value.ToString("g"), Value = value.ToString("d") };
        var semiJson = JObject.FromObject(nameAndValue);
        semiJson.WriteTo(writer);
    }
}

字符串

  • 我将T限制为System.Enum
  • WriteJson中,我创建了一个匿名类型,并使用Enum Format strings检索所需的值
  • 我不得不从匿名类型创建一个JObject,因为JsonWriter不直接支持它

然后,可以使用以下属性修饰模型类:

public class Product
{
    [JsonConverter(typeof(EnumConverter<DisplayStatus>))]
    public DisplayStatus DisplayStatus { get; set; }
    [JsonConverter(typeof(EnumConverter<DrugClass>))]
    public DrugClass DrugClass { get; set; }
    [JsonConverter(typeof(EnumConverter<DrugType>))]
    public DrugType DrugType { get; set; }
}


最后,序列化逻辑看起来像这样:

var product = new Product() 
{
    DisplayStatus = DisplayStatus.Visible,
    DrugClass = DrugClass.Generic,
    DrugType = DrugType.Drug,
};
var result = JsonConvert.SerializeObject(
    new { Product = product },
    new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });


result看起来像这样:

{
   "product":{
      "displayStatus":{
         "Name":"Visible",
         "Value":"1"
      },
      "drugClass":{
         "Name":"Generic",
         "Value":"1"
      },
      "drugType":{
         "Name":"Drug",
         "Value":"1"
      }
   }
}


为了固定NameValue的 shell ,您需要做的就是将serializer传递给FromObject

var details = JObject.FromObject(nameAndValue, serializer);


在此之后,最终结果将与预期相同:

{
   "product":{
      "displayStatus":{
         "name":"Visible",
         "value":"1"
      },
      "drugClass":{
         "name":"Generic",
         "value":"1"
      },
      "drugType":{
         "name":"Drug",
         "value":"1"
      }
   }
}

UDPATE #1:将转换器添加到设置

正如注解中所指出的,Product类不能用JsonConverterAttribute s修改。所以,如果你有这个限制,那么你可以通过JsonSettings对象传递转换器来克服这个限制,就像这样:

var settings = new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver(),
    Converters = new JsonConverter[] {
        new EnumConverter<DisplayStatus>(),
        new EnumConverter<DrugClass>(),
        new EnumConverter<DrugType>()
    }
};

var result = JsonConvert.SerializeObject(new { Product = product }, settings);


使用这种方法,您的模型将是无序列化属性的:)

g52tjvyc

g52tjvyc2#

注意,你不应该真的需要这样的东西,有几种开箱即用的方法来转换 * 枚举 *。例如StringEnumConverter。例如

[JsonConverter(typeof(StringEnumConverter))]

字符串
然而,纯粹出于病态的好奇心和学术兴趣

给定转换器

public class SomeConverter : JsonConverter 
{

   public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
   {
      writer.WriteStartObject();
      writer.WritePropertyName("name");
      writer.WriteValue(value.ToString());
      writer.WritePropertyName("value");
      writer.WriteValue(Convert.ChangeType(value,typeof(int)));
      writer.WriteEndObject();
   }

   public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
   {
      // ill leave this up to your imagination
      throw new NotImplementedException();
   }

   public override bool CanConvert(Type objectType)
   {
     return objectType == typeof(Enum);
   }
}

枚举

public enum Bob
{
   one,
   two
}
public enum Blerge
{
   Asd,
   BFG
}

和类

public class Product
{
   [JsonConverter(typeof(SomeConverter))]
   public Bob Bob { get; set; }

   [JsonConverter(typeof(SomeConverter))]
   public Blerge Blerge { get; set; }
}

用法

var asd = new Product()
{
   Bob = Bob.two,
   Blerge = Blerge.Asd
};

var bla = JsonConvert.SerializeObject(asd, Formatting.Indented);
Console.WriteLine(bla);

输出

{
  "Bob": {
    "name": "two",
    "value": 1
  },
  "Blerge": {
    "name": "Asd",
    "value": 0
  }
}

相关问题