假设有以下泛型类和内部类型类:
public class Generic<T>
where T : class
{
public bool IsSuccess { get; set; }
public string Message { get; set; }
public T Data { get; set; }
}
public class Specific
{
public string Name { get; set; }
public int Id { get; set; }
}
有没有办法让 Newtonsoft/Json.NET 序列化它们而不将它们封装在“数据”中,例如:
{"IsSuccess":true,"Message":"Success","Name":"Test","Id":1}
而不是:
{"IsSuccess":true,"Message":"Success","Data":{"Name":"Test","Id":1}}
简单的方法产生封装:
JsonConvert.SerializeObject(myGenericObject);
我知道我可以通过经典继承来实现这一点(
Specific : Generic
),但我正在尝试其他方法,我想在我不想要 Generic
属性的上下文中重用我的特定类。
是的,您可以通过创建自定义 JsonConverter 来完成此操作。但是,由于 Newtonsoft.Json 不太喜欢它们,因此您还需要传入 DefaultContractResolver,以便它能够使用新的转换器。
转换器可以改进,只是为了表明这是可能的。
您还必须使用 JsonConverter 属性来装饰您的 Generic:
[JsonConverter(typeof(GenericConverter<>))]
public class Generic<T> where T : class
{
public bool IsSuccess { get; set; }
public string Message { get; set; }
public T Data { get; set; }
}
转换器:
public class GenericConverter<T> : JsonConverter<Generic<T>> where T : class
{
public override void WriteJson(JsonWriter writer, Generic<T> value, JsonSerializer serializer)
{
JObject obj = new JObject(
new JProperty("IsSuccess", value.IsSuccess),
new JProperty("Message", value.Message)
);
// Check if Data is not null and add its properties to the JObject
if (value.Data != null)
{
var dataObject = JObject.FromObject(value.Data, serializer);
obj.Merge(dataObject, new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Union
});
}
obj.WriteTo(writer);
}
public override Generic<T> ReadJson(JsonReader reader, Type objectType, Generic<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanRead => false;
}
合同解析者:
public sealed class GenericConverterContractResolver : DefaultContractResolver
{
protected override JsonConverter ResolveContractConverter(Type objectType)
{
var typeInfo = objectType.GetTypeInfo();
if (typeInfo.IsGenericType && !typeInfo.IsGenericTypeDefinition)
{
var jsonConverterAttribute = typeInfo.GetCustomAttribute<JsonConverterAttribute>();
if (jsonConverterAttribute != null && jsonConverterAttribute.ConverterType.GetTypeInfo().IsGenericTypeDefinition)
{
return (JsonConverter)Activator.CreateInstance(jsonConverterAttribute.ConverterType.MakeGenericType(typeInfo.GenericTypeArguments), jsonConverterAttribute.ConverterParameters);
}
}
return base.ResolveContractConverter(objectType);
}
}
然后你像这样使用它:
var settings = new JsonSerializerSettings
{
ContractResolver = new GenericConverterContractResolver()
};
string json = JsonConvert.SerializeObject(genericInstance, settings);