我可以将json解析为字符串或其他具体类型的对象吗?
作者:互联网
我想拥有类型对象的属性,该属性可以是字符串或模板类型.
是否可以告诉Json.NET将某些内容解析为几种指定类型之一?
class MyClass
{
public object Template { get; set; }
}
其中Template =“ TemplateName”
{
"Template": "TemplateName"
}
或Template = new Template()
{
"Template": { "Name": "OtherTamplate", ... }
}
更新:
我试图遵循@krillgar的建议并创建一个自定义的JsonConverter,但不幸的是,CanConvert方法仅接收目标类型,在这种情况下为对象.该信息不足以告诉我们可以反序列化(如果我有其他对象属性).我想我毕竟需要它作为一个模板,或者创建一个派生类型,例如TemplateReference或类似的东西:
class myconverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
// objectType = typeof(object)
throw new NotImplementedException();
}
}
Configuration = JsonConvert.DeserializeObject<MyClass>(text, new myconverter());
免责声明
这个问题曾经作为How to deserialize a JSON property that can be two different data types using Json.NET的副本被关闭.因为在撰写我的问题时,我还不知道已经有一个类似的问题,我想澄清它们之间的区别,以防止将来被关闭. :
另一个问题是关于如何将不同的值反序列化为具体类型,而我的是关于将不同的值反序列化为对象.乍一看似乎是一样的,因为在两个示例中,属性的类型都是不同的,但它对整个应用程序设计有巨大的影响.对我而言,重要的是我可以使用一个对象来存储不同的专用类型,而不是一个具有多个职责的类型.
解决方法:
通过使用自定义JsonConverter
可以解决此问题.以下是适用于这种情况的通用版本:
class ObjectOrStringConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
// CanConvert is not called when the [JsonConverter] attribute is used
return false;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
{
return token.ToObject<T>(serializer);
}
return token.ToString();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
要使用转换器,您需要做的就是向类中的属性添加[JsonConverter]属性,该属性可以是字符串或对象.通用类型参数必须与您期望的非字符串对象的类型匹配.
class MyClass
{
[JsonConverter(typeof(ObjectOrStringConverter<Template>))]
public object Template { get; set; }
}
以下是实际使用的转换器的演示:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("--- first run ---");
string json = @"
{
""Template"": ""TemplateName""
}";
DeserializeAndDump(json);
Console.WriteLine("--- second run ---");
json = @"
{
""Template"": { ""Name"": ""OtherTemplate"" }
}";
DeserializeAndDump(json);
}
static void DeserializeAndDump(string json)
{
MyClass obj = JsonConvert.DeserializeObject<MyClass>(json);
if (obj.Template == null)
{
Console.WriteLine("Template property is null");
}
else
{
Console.WriteLine("Template property is a " + obj.Template.GetType().Name);
string name = "(unknown)";
if (obj.Template is Template) name = ((Template)obj.Template).Name;
else if (obj.Template is string) name = (string)obj.Template;
Console.WriteLine("Template name is \"" + name + "\"");
}
Console.WriteLine();
}
}
class Template
{
public string Name { get; set; }
}
这是上面的输出:
--- first run ---
Template property is a String
Template name is "TemplateName"
--- second run ---
Template property is a Template
Template name is "OtherTemplate"
小提琴:https://dotnetfiddle.net/Lw3RaN
标签:json-net,json,c 来源: https://codeday.me/bug/20191119/2037396.html