我与基于JSON的API进行通信,我无法改变。它始终返回一个Response对象,其中包含不同的Result对象。通常它看起来像这样:
{" ver":" 2.0","结果":{"代码":0}}
对于某些命令,Result对象已经“生长”。通过添加额外的属性:
{" ver":" 2.0","结果":{"代码":0," hostName&# 34;:"示例"," hostPort":5000}}
我使用Newtonsoft属性来定义对象,如下所示:
internal class RpcResponse { [JsonProperty(PropertyName = "ver")] public string Version { get; set; } [JsonProperty(PropertyName = "result")] public RpcResponseResult Result { get; set; } internal class RpcResponseResult { [JsonProperty(PropertyName = "code")] public int Code { get; set; } } internal class RpcExtendedResponseResult: RpcResponseResult { [JsonProperty(PropertyName = "hostName")] public string HostName { get; set; } [JsonProperty(PropertyName = "hostPort")] public int HostPort { get; set; }
但是当反序列化反序列化时:
RpcResponse rspResponse = JsonConvert.DeserializeObject<RpcResponse>(rspString);
其Result属性始终显示为RpcResponseResult对象,即。 JsonConvert并不知道将它构造为RpcExtendedResponseResult对象。
是否有某种方法可以使用属性或转换器来恢复正确的后代对象?我觉得我错过了一些明显的东西!
答案 0 :(得分:1)
这是因为对象的类型是RpcResponseResult。反序列化程序只能反序列化在指定字段类型中声明的字段。它无法确定,因为类具有“hostName”,现在它是RpcExtendedResponseResult。
如果我这样做,我可以根据需要将结果作为所有可能字段的容器,并使用默认值,然后根据需要填充另一个对象。
internal class RpcResponseResultContainer
{
[JsonProperty(PropertyName = "code")]
public int Code { get; set; }
[JsonProperty(PropertyName = "hostName")]
private string mHostName = string.Empty;
public string HostName
{
get { return mHostName;}
set { mHostName = value; }
}
[JsonProperty(PropertyName = "hostPort")]
private int mHostPort = -1;
public int HostPort
{
get { return mHostPort;}
set { mHostPort = value;}
}
然后,如果你真的希望得到你想要的对象,你可以在容器类中做这样的事情:
public RpcResponseResult GetActualResponseType()
{
if(HostPort != -1 && !string.IsNullOrEmtpy(HostName))
{
return new RpcExtendedResponseResult() { Code = this.Code, HostName = this.HostName, HostPort = this.HostPort};
}
return new RpcResponseResult() { Code = this.Code };
}
答案 1 :(得分:0)
首先,感谢Matthew Frontino提供了我接受的唯一答案。
但是我选择不制作单个结果容器,所以这就是我最终做的事情。
我添加了Dribbel建议的CanWrite覆盖:
public override bool CanWrite
{
get { return false; }
}
我还将自己的帮助函数添加到JsonCreationConverter:
protected bool FieldExists(string fieldName, JObject jObject) {
return jObject[fieldName] != null;
}
然后我按如下方式创建了自己的转换器:
class RpcResponseResultConverter : JsonCreationConverter<RpcResponseResult>
{
protected override RpcResponseResult Create(Type objectType, JObject jObject)
{
// determine extended responses
if (FieldExists("hostName", jObject) &&
FieldExists("hostPort", jObject) )
{
return new RpcExtendedResponseResult();
}
//default
return new RpcResponseResult();
}
}
然后我反序列化顶级类并提供要使用的任何转换器。在这种情况下,我只提供了一个,这是针对所讨论的嵌套类:
RpcResponse rspResponse = JsonConvert.DeserializeObject<RpcResponse>(
rspString,
new JsonSerializerSettings {
DateParseHandling = Newtonsoft.Json.DateParseHandling.None,
Converters = new List<JsonConverter>( new JsonConverter[] {
new RpcResponseResultConverter()
})
});
注意: