在我的API中,我想让消费者选择将属性作为字符串标识符或对象发送,例如:
{
"source": "token_xyz"
}
或者
{
"source": {
"name": "test"
}
}
根据类型(字符串或对象),我想在班上设置特定属性:
public class MyRequest
{
[JsonProperty("source")]
public SourceUser SourceUser { get; set; }
[JsonProperty("source")]
public string SourceToken { get; set; }
}
正如您所看到的,我尝试使用JsonProperty("source")
修饰这两个属性,但不幸的是,这不起作用 - 该对象无法反序列化。
如何根据JSON类型反序列化到适当的属性?
答案 0 :(得分:2)
Json.NET不支持具有相同合同属性名称的两个属性,可能是因为,如JSON RFC中所述:
名称都是唯一的对象在某种意义上是可互操作的 接收该对象的所有软件实现都会同意 名称 - 值映射。当对象中的名称不是 独特的,接收这样一个对象的软件的行为是 不可预测的。
因此,您需要某种custom JsonConverter
来反序列化"source"
属性。一种简单的方法是将转换器应用于设置&的私有Source
属性。根据需要获得SourceUser
或SourceToken
:
public class MyRequest
{
[JsonConverter(typeof(SourceConverter))]
[JsonProperty]
object Source
{
get
{
// Possibly throw an exception if both are non-null?
return SourceUser ?? (object)SourceToken;
}
set
{
SourceUser = value as SourceUser;
SourceToken = value as string;
}
}
[JsonIgnore]
public SourceUser SourceUser { get; set; }
[JsonIgnore]
public string SourceToken { get; set; }
}
class SourceConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException("This converter is intended to be applied with [JsonConverter(typeof(SourceConverter))]");
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
else if (reader.TokenType == JsonToken.StartObject)
return serializer.Deserialize<SourceUser>(reader);
else
return (string)JValue.Load(reader);
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
示例fiddle。