![](/img/trans.png)
[英]Deserialise JSON object to string or concrete type based on status code returned
[英]Can I parse json either into a string or another concrete type as object?
我想拥有类型object
属性,可以是string
或Template
类型。
是否有可能告诉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<MyClass>(text, new myconverter());
此问题曾作为如何使用Json.NET反序列化可能是两种不同数据类型的JSON属性的副本而关闭。 因为在撰写我的问题时,我不知道已经有类似的问题,我想澄清它们之间的区别,以防止它在将来被关闭:
另一个问题是如何将不同的值反序列化为具体类型,而我的是将不同的值反序列化为对象 。 在第一次看起来似乎是相同的,因为在两个示例中,只有属性的类型不同,但它对整个应用程序设计有巨大影响。 对我来说很重要的是,我可以使用一个对象来存储不同的专用类型,而不是一种具有多种职责的类型。
使用自定义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
我不知道你是否可以这样做,但你可以采取另一种方式。 将“Template”属性更改为Template
而不是object
并使用Template
类的自定义属性来了解要将其序列化为Template
或string
。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.