我可以将json解析为字符串或其他具体类型作为对象吗?

我想拥有类型object属性,可以是stringTemplate类型。

是否有可能告诉Json.NET将某些内容解析为几种指定类型之一?

 class MyClass { public object Template { get; set; } } 

其中Template = "TemplateName"

 { "Template": "TemplateName" } 

Template = new Template()

 { "Template": { "Name": "OtherTamplate", ... } } 

更新:

我试图遵循@krillgar的建议并创建一个自定义的JsonConverter但不幸的是CanConvert方法只接收目标类型,在这种情况下是object 。 这些信息不足以告诉它可以反序列化(如果我有其他object属性)。 我想我毕竟需要它是一个Template或创建像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(text, new myconverter()); 

放弃

此问题曾作为如何使用Json.NET反序列化可能是两种不同数据类型的JSON属性的副本而关闭。 因为在撰写我的问题时,我不知道已经有类似的问题,我想澄清它们之间的区别,以防止它在将来被关闭:

另一个问题是如何将不同的值反序列化为具体类型,而我的是将不同的值反序列化为对象 。 在第一次看起来似乎是相同的,因为在两个示例中,只有属性的类型不同,但它对整个应用程序设计有巨大影响。 对我来说,重要的是我可以使用一个对象来存储不同的专用类型,而不是一种具有多种职责的类型。

使用自定义JsonConverter可以解决此问题。 这是适用于这种情况的通用版本:

 class ObjectOrStringConverter : 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(serializer); } return token.ToString(); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.Serialize(writer, value); } } 

要使用转换器,您需要做的就是在类中的属性中添加[JsonConverter]属性,该属性可以是字符串或对象。 generics类型参数必须与您期望的非字符串对象的类型匹配。

 class MyClass { [JsonConverter(typeof(ObjectOrStringConverter 

下面是转换器运行的演示:

 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(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

我不知道你是否可以这样做,但你可以采取另一种方式。 将“模板”属性更改为Template而不是object并使用Template类的自定义属性来了解要将其序列化为Templatestring

 class MyClass { [JsonConverter(typeof(TemplateConverter))] public Template Template { get; set; } } class Template { /* Your Template class */ public Type TypeToSerializeInto { get; private set; } } public class TemplateConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(Template); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { Template val = value as Template; writer.WriteStartObject(); writer.WritePropertyName("Template"); if (val.TypeToSerializeInto == typeof(Template)) serializer.Serialize(writer, val); else if (val.TypeToSerializeInto == typeof(string)) serializer.Serialize(writer, val.Name); writer.WriteEndObject(); } } 

如果您有一个属性,哪个类型是类似抽象类型的对象,那么在反序列化时,您可以通过序列化某个特定类型的名称来了解序列化的特定类型。 所以你的json应该是这样的:

{“MyClass”:{“Template”:“some name”,“type”:“System.String”}}

这种方式在反序列化时,您可以在序列化之前检查该属性的类型(在本例中为String)

确定类型的另一种方法是检查json结构,如下所示: C#:当一个字段可以是不同类型时反序列化JSON