将JSON反序列化为派生类

时间:2017-01-20 17:31:43

标签: c# .net json serialization deserialization

{
    "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中的反序列化期间使用反射来确定来自&#34; name&#34;值。我也研究了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;
    }

2 个答案:

答案 0 :(得分:0)

首先,一些注意事项 - 我不使用JSonConvert,但有文章向您展示如何使用它。例如,请参阅Json.net serialize/deserialize derived types?。但是,你没有包含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 

答案 1 :(得分:0)

使用此作为我的解决方案。

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