简体   繁体   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.
    }
}

When trying to deserialize Class1, I can't figure out how to create the list of derived classed from name. 当尝试反序列化Class1时,我不知道如何创建从名称派生的分类列表。 I can't declare something like List BaseClass where BaseClass is abstract and I'm not sure how to use reflection during deserialization within Class2 to determine the derived class from the "name" value. 我无法声明类似List BaseClass的名称,其中BaseClass是抽象的,我不确定如何在Class2中反序列化期间使用反射来确定“名称”值的派生类。 I also looked into ICloneable but didn't get anywhere with it in this context. 我也研究了ICloneable,但在这种情况下却一无所获。

Edit: 编辑:

Here is what I ended up creating and calling from get and set 这就是我最终从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;
    }

First, some notes - I don't use JSonConvert, but there are articles that show you how to do this with. 首先,一些注意事项-我不使用JSonConvert,但是有些文章向您展示了如何使用它。 See Json.net serialize/deserialize derived types? 请参阅Json.net序列化/反序列化派生类型? , for example. , 例如。 However, you didn't include a json.net tag, so I'm assuming this should hopefully help, or at least point you to the right place. 但是,您没有包含json.net标记,因此我认为这应该会有所帮助,或者至少将您指向正确的位置。

I used the built in .Net JavaScriptSerializer. 我使用了内置的.Net JavaScriptSerializer。 You may need to adjust this to work with your input. 您可能需要对此进行调整以使用您的输入。 I created my input based on your code, and my json looks nothing like yours. 我根据您的代码创建了输入,而json看起来与您的不同。 So, you may still have some work left. 因此,您可能还有一些工作要做。 I was able to get it working with a SimpleTypeResolver. 我能够使它与SimpleTypeResolver一起使用。 Code below: 代码如下:

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.
        }
    }
}
}

my output json (with the SimpleTypeResolver): 我的输出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"}]}

and without the type resolver, for comparison (causes errors): 并且没有类型解析器,用于比较(导致错误):

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

And once I deserialize (in the for loop, Console.WriteLine)... 然后我反序列化(在for循环中,Console.WriteLine)...

DerivedV1

WindowsFormsApplication6.Form1+DerivedV1

DerivedV2

WindowsFormsApplication6.Form1+DerivedV2

DerivedV3

WindowsFormsApplication6.Form1+DerivedV3 

Using this as my solution. 用这个作为我的解决方案。

  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