在我正在使用的项目模型中,我使用了一个
模型有一个基类,看起来像这样:
尝试反序列化由Web API返回的JSON对象时,对于第一个CustomerModel对象,CreatedBy和ModifiedBy属性将是正确的。然而,对于第二个CustomerModel对象,这些属性将是新的UserModel实例,没有设置任何属性。
为了反序列化JSON字符串,我正在使用以下代码:
我该如何正确设置所有反序列化对象的属性?
编辑:
问题似乎出现在serializer.Populate(reader, existingValue)中,引用没有被记住。
JsonConverter
属性来帮助对这些模型进行(反)序列化。当前转换器的代码如下:public class CustomJsonConverter : Newtonsoft.Json.JsonConverter
{
bool _canWrite = true;
public override bool CanWrite
{
get { return _canWrite; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
serializer.DefaultValueHandling = DefaultValueHandling.Ignore;
serializer.NullValueHandling = NullValueHandling.Ignore;
_canWrite = false;
var jObject = JObject.FromObject(value, serializer);
_canWrite = true;
jObject.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
serializer.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
if (reader.TokenType == JsonToken.StartObject)
{
existingValue = existingValue ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
serializer.Populate(reader, existingValue);
return existingValue;
}
else if (reader.TokenType == JsonToken.Null)
{
return null;
}
else
{
throw new JsonSerializationException();
}
}
public override bool CanConvert(Type objectType)
{
return typeof(IModelBase).IsAssignableFrom(objectType);
}
}
模型有一个基类,看起来像这样:
[JsonConverter(typeof(CustomJsonConverter))]
public abstract class ModelBase : IModelBase
{
public string ID { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime ModifiedAt { get; set; }
}
ModelBase
类的派生类具有类型也派生自ModelBase
的属性。例如:
public class CustomerModel : ModelBase
{
public string Name { get; set; }
public UserModel CreatedBy { get; set; }
public UserModel ModifiedBy { get; set; }
}
public class UserModel : ModelBase
{
public string Name { get; set; }
public UserModel CreatedBy { get; set; }
public UserModel ModifiedBy { get; set; }
}
我将这些模型用于ASP.NET Web API 2应用程序(服务器端)和C#应用程序(客户端)。对于大多数API调用,都会返回一组模型。在序列化模型时,一切都按预期工作。但是,在反序列化时,只有每个引用的第一个出现会填充信息。
例如:
[
{
"$id": "1",
"Name": "Customer1",
"CreatedBy": {
"$id": "2",
"ID": "1",
"Name": "User1"
},
"ModifiedBy": {
"$id": "3",
"ID": "3",
"Name": "User3"
},
"ID": "1",
"CreatedAt": "2019-02-06T00:00:04",
"ModifiedAt": "2019-02-06T00:20:12"
},
{
"$id": "4",
"Name": "Customer2",
"CreatedBy": {
"$ref": "2"
},
"ModifiedBy": {
"$ref": "2"
},
"ID": "2",
"CreatedAt": "2019-02-06T00:10:00",
"ModifiedAt": "2019-02-06T00:10:00"
}
]
尝试反序列化由Web API返回的JSON对象时,对于第一个CustomerModel对象,CreatedBy和ModifiedBy属性将是正确的。然而,对于第二个CustomerModel对象,这些属性将是新的UserModel实例,没有设置任何属性。
为了反序列化JSON字符串,我正在使用以下代码:
using (var sr = new StreamReader(streamFromWebAPICall))
{
using (var jtr = new JsonTextReader(sr))
{
var js = new JsonSerializer();
return js.Deserialize(jtr, objectType);
}
}
我该如何正确设置所有反序列化对象的属性?
编辑:
问题似乎出现在serializer.Populate(reader, existingValue)中,引用没有被记住。
$ref
和$id
属性,就像自定义对象序列化 vs PreserveReferencesHandling中所示。 - dbcCustomJsonConverter
转换器中尝试做什么?是为了递归地为给定类型及其所有后代对象启用特定的序列化器选项吗? - dbc