繁体   English   中英

将JSON反序列化为派生类

[英]Deserialize JSON into Derived classes

{
    "Class1": {
        "Class2": [
            {"Name": "DerivedV1"},
            {"Name": "DerivedV2"},
            {"Name": "DerivedV3"}
        ]
    }
}

JsonConvert.DeserializeObject<Class1>(jsonString, settings);

public class Class1
{
    public List<BaseClass> DerivedClasses { get; set; }
}

public abstract BaseClass
{
    public string Name { get; set; }

    public abstract bool DoSomething;
}

public class DerivedV1 : BaseClass
{
    public override bool DoSomething()
    {
        // Logic here, different for each derived class.
    }
}

当尝试反序列化Class1时,我不知道如何创建从名称派生的分类列表。 我无法声明类似List BaseClass的名称,其中BaseClass是抽象的,我不确定如何在Class2中反序列化期间使用反射来确定“名称”值的派生类。 我也研究了ICloneable,但在这种情况下却一无所获。

编辑:

这就是我最终从get和set创建和调用的结果

    public static List<T> DeserializeJObjectsToObjects<T>(IEnumerable<JObject> jObjects, string typeKey, string nameSpaceOfClass)
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        List<T> convert = new List<T>();

        foreach (var jObject in jObjects)
        {
            JToken typeName;
            jObject.TryGetValue(typeKey, out typeName);
            string fullNameSpace = string.Format(namespaceFormat, nameSpaceOfClass, typeName);
            Type t = Type.GetType(string.Format(fullNameSpace));
            convert.Add((T) Activator.CreateInstance(t));
        }

        return convert;
    }

    public static List<JObject> SerializeObjectsToJObjects<T>(IEnumerable<T> variableObjects )
    {
        List<JObject> convert = new List<JObject>();

        foreach (T variableObject in variableObjects)
        {
            var jsonString = JsonConvert.SerializeObject(variableObject);
            convert.Add(JObject.Parse(jsonString));
        }

        return convert;
    }

首先,一些注意事项-我不使用JSonConvert,但是有些文章向您展示了如何使用它。 请参阅Json.net序列化/反序列化派生类型? , 例如。 但是,您没有包含json.net标记,因此我认为这应该会有所帮助,或者至少将您指向正确的位置。

我使用了内置的.Net JavaScriptSerializer。 您可能需要对此进行调整以使用您的输入。 我根据您的代码创建了输入,而json看起来与您的不同。 因此,您可能还有一些工作要做。 我能够使它与SimpleTypeResolver一起使用。 代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace WindowsFormsApplication6
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Class1 oClass = new Class1();
        DerivedV1 v1 = new DerivedV1();
        v1.Name = "DerivedV1";
        oClass.DerivedClasses.Add(v1);
        DerivedV2 v2 = new DerivedV2();
        v2.Name = "DerivedV2";
        oClass.DerivedClasses.Add(v2);
        DerivedV3 v3 = new DerivedV3();
        v3.Name = "DerivedV3";
        oClass.DerivedClasses.Add(v3);
        JavaScriptSerializer ser = new JavaScriptSerializer(new SimpleTypeResolver());
        string sSer = ser.Serialize(oClass);

        var test =ser.Deserialize(sSer,typeof(Class1));
        foreach (var tst in ((Class1)test).DerivedClasses)
        {
            Console.WriteLine(tst.Name + Environment.NewLine);
            Console.WriteLine(tst.GetType().ToString() + Environment.NewLine);
        }
    }
    public class Class1
    {
        public List<BaseClass> DerivedClasses { get; set; }
        public Class1()
        {
            DerivedClasses = new List<BaseClass>();
        }
    }
    public abstract class BaseClass
    {
        public string Name { get; set; }
        private bool _dosom;

        public abstract bool DoSomething();
        public BaseClass(){}
    }       
    public class DerivedV1 : BaseClass
    {
        public override bool DoSomething()
        {
            return true;
            // Logic here, different for each derived class.
        }
    }
    public class DerivedV2 : BaseClass
    {
        public override bool DoSomething()
        {
            return false;
            // Logic here, different for each derived class.
        }
    }
    public class DerivedV3 : BaseClass
    {
        public override bool DoSomething()
        {
            return true;
            // Logic here, different for each derived class.
        }
    }
}
}

我的输出json(使用SimpleTypeResolver):

{"__type":"WindowsFormsApplication6.Form1+Class1, WindowsFormsApplication6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","DerivedClasses":[{"__type":"WindowsFormsApplication6.Form1+DerivedV1, WindowsFormsApplication6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Name":"DerivedV1"},{"__type":"WindowsFormsApplication6.Form1+DerivedV2, WindowsFormsApplication6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Name":"DerivedV2"},{"__type":"WindowsFormsApplication6.Form1+DerivedV3, WindowsFormsApplication6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Name":"DerivedV3"}]}

并且没有类型解析器,用于比较(导致错误):

{"DerivedClasses":[{"Name":"DerivedV1"},{"Name":"DerivedV2"},{"Name":"DerivedV3"}]}

然后我反序列化(在for循环中,Console.WriteLine)...

DerivedV1

WindowsFormsApplication6.Form1+DerivedV1

DerivedV2

WindowsFormsApplication6.Form1+DerivedV2

DerivedV3

WindowsFormsApplication6.Form1+DerivedV3 

用这个作为我的解决方案。

  public static List<T> DeserializeJObjectsToObjects<T>(IEnumerable<JObject> jObjects, string typeKey, string nameSpaceOfClass)
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        List<T> convert = new List<T>();

        foreach (var jObject in jObjects)
        {
            JToken typeName;
            jObject.TryGetValue(typeKey, out typeName);
            string fullNameSpace = string.Format(nameSpaceFormat, nameSpaceOfClass, typeName);
            Type t = Type.GetType(string.Format(fullNameSpace));
            convert.Add((T) Activator.CreateInstance(t));
        }

        return convert;
    }

    public static List<JObject> SerializeObjectsToJObjects<T>(IEnumerable<T> variableObjects )
    {
        List<JObject> convert = new List<JObject>();

        foreach (T variableObject in variableObjects)
        {
            var jsonString = JsonConvert.SerializeObject(variableObject);
            convert.Add(JObject.Parse(jsonString));
        }

        return convert;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM