我可以将json解析为字符串还是其他具体类型作为对象? [英] Can I parse json either into a string or another concrete type as object?

查看:107
本文介绍了我可以将json解析为字符串还是其他具体类型作为对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要具有object类型的属性,该属性可以是stringTemplate类型.

I'd like to have property of type object that can be either a string or Template type.

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

Is it possible to tell Json.NET to parse something into one of several specified types?

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

其中Template = "TemplateName"

{
    "Template": "TemplateName"
}

Template = new Template()

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


更新:


UPDATE:

我试图遵循@krillgar的建议并创建一个自定义的JsonConverter,但是很遗憾,CanConvert方法仅接收目标类型,在这种情况下为object.该信息不足以告诉我们可以反序列化(如果我具有其他object属性).我想我毕竟需要它是Template或创建类似TemplateReference之类的派生类型:

I tried to follow @krillgar' advice and create a custom JsonConverter but unfortunatelly the CanConvert method receives only the target type, in this case object. This information is not enough to tell wheter it can be deserialized (in case I had other object properties). I guess I need it to be a Template after all or create a derived type like TemplateReference or something:

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


免责声明

该问题曾经作为


Disclaimer

This question has once been closed as a duplicate of How to deserialize a JSON property that can be two different data types using Json.NET. Because at the time of writing my question I hadn't known that there already was a similar one I'd like to clarify the difference between them to prevent it from being closed in future:

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

The other question is about how to deserialize different values into a concrete type whereas mine is about deserializing different values into an object. It might seem to be the same at the first look because in both examples only the type of the property is different but it has a huge impact on the overall application design. It's important for me that I can use an object to store different specialized types rather then one type having multiple responsibilities.

推荐答案

可以通过使用自定义

This problem can be solved by using a custom JsonConverter. Here is a generic version that should work for this situation:

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]属性,该属性可以是字符串或对象.通用类型参数必须与您期望的非字符串对象的类型匹配.

To use the converter, all you need to do is add a [JsonConverter] attribute to the property in your class that can be either a string or an object. The generic type parameter must match the type of non-string object you are expecting.

class MyClass
{
    [JsonConverter(typeof(ObjectOrStringConverter<Template>))]
    public object Template { get; set; }
}

以下是正在运行的转换器的演示:

Below is a demonstration of the converter in action:

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解析为字符串还是其他具体类型作为对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆