我正在使用WebAPI,它依赖于JSON . net的JSON格式。在c#方面,我有一个DTO,看起来像这样:
public class DTO1 : IManifestContainer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public HashSet<string> Manifest { get; private set; }
}
public interface IManifestContainer
{
HashSet<string> Manifest { get; }
}
IManifestContainer接口的思想是跟踪客户端在JSON对象中实际发送给服务器的属性。例如,如果客户端发送以下JSON:
{"FirstName":"Jojo"}
Manifest hashset将只包含"FirstName"。如果客户端发送:
{"FirstName":"Jojo", "LastName":"Jones"}
Manifest hashset将同时包含"FirstName"one_answers"LastName"。
我尝试实现这样一个JsonConverter:
public class ManifestJsonConverter : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
JObject jObject = JObject.Load(reader);
// Convert the JObject to a C# object??
// Passing the serializer will call this method again
object retVal = jObject.ToObject(objectType, serializer);
IManifestContainer manifestContainer = (IManifestContainer) retVal;
foreach (var jProperty in jObject.Properties())
{
manifestContainer.Manifest.Add(jProperty.Name);
}
return retVal;
}
public override bool CanConvert(Type objectType)
{
return typeof (IManifestContainer).IsAssignableFrom(objectType);
}
}
我需要加载JObject以获得来自客户端的所有属性,但随后我不知道如何从JObject创建"objectType"(c# DTO)的实例。
看完这篇文章后,我想出了这个实现。
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
JObject jObject = JObject.Load(reader);
JArray manifestArray = new JArray();
foreach (var jProperty in jObject.Properties())
{
manifestArray.Add(jProperty.Name);
}
jObject["Manifest"] = manifestArray;
var retVal = Activator.CreateInstance(objectType);
serializer.Populate(jObject.CreateReader(), retVal);
return retVal;
}
您可以尝试使用不占用JsonSerializer
的JObject.ToObject
过载。在这种情况下,ToObject
方法将使用一个新的序列化器实例,它不知道转换器,这应该允许它工作,只要你没有用[JsonConverter]
属性装饰你的DTO类。
object retVal = jObject.ToObject(objectType);
如果这不起作用,您的另一个选择是手动创建DTO实例并通过反射填充其属性。