在JSON通用属性序列化中包含类名

时间:2017-01-31 23:54:42

标签: c# json serialization asp.net-web-api asp.net-web-api2

我创建了以下类来表示REST API请求的任何服务器响应:

[DataContract]
public class ServerResponse<T>
{
    [DataMember(Name = "error")]
    public string ErrorMessage { get; set; }

    [DataMember(Name = "data")]
    public T Data { get; set; }

    [DataMember(Name = "success")]
    public bool Success { get; set; } 
}

当使用像这样的简单类时

[DataContract(Name = "category")]
public class Category
{
    [DataMember(Name = "id")]
    public int Id { get; set; }

    [DataMember(Name = "name")]
    public string Name { get; set; }
}

我得到以下回复

{
  "error": "",
  "data": {
      "id": 3,
      "name": "Top"
   },
  "success": true
}

我想在序列化中包含泛型类名。想要的结果:

{
  "error": "",
  "data": {
      "category": {
          "id": 3,
          "name": "Top"
      }
   },
  "success": true
}

我该怎么做? (我在类似的帖子中看到过答案,但不适用于像这样的通用场景)

1 个答案:

答案 0 :(得分:0)

我发布我的解决方法,如果它可以帮助任何人

我已经创建了一个自定义Json转换器

public class GenericTypeJsonSerializer : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // Parse data object
        var dataObject = JToken.FromObject(value);

        // Extract generic type class serialization name
        var className = ExtractClassName(value);

        // Create wrapper object that includes generic class name
        JObject wrapperObject = new JObject();
        wrapperObject.Add(className, dataObject);

        // write object
        wrapperObject.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public string ExtractClassName(object value)
    {
        // extract data contract attribute
        var dataContractAttribute = value.GetType()
            .GetCustomAttribute(typeof(DataContractAttribute)) as DataContractAttribute;
        // return name declared in attribute
        if (dataContractAttribute?.Name != null)
            return dataContractAttribute.Name;

        // return default class name
        return value.GetType().Name;
    }
}

我使用Data属性

修饰了通用JsonConverter属性
    [JsonConverter(typeof(GenericTypeJsonSerializer))]
    [DataMember(Name = "data")]
    public T Data { get; set; }

c'est tout!