编程手动JSON反序列化为C#对象

编程手动JSON反序列化为C#对象,c#,json,reflection,json.net,deserialization,C#,Json,Reflection,Json.net,Deserialization,我们有一个非常大的平面C#对象(20000ish属性),我们正在使用Newtonsoft JSON反序列化器将JSON对象反序列化到其中 由于反射,目前需要3分钟以上的时间 我们希望实现一个程序化的手动反序列化过程,以减少这段时间 我们已经阅读了大量有关这方面的参考资料,这些资料提供了如何进行手动反序列化的一般思路,但没有解释如何以编程方式进行反序列化 e、 g 例如,我们有一个具有20000个属性的大型购买对象,没有子类/对象属性,实际上是20000多个字符串。它们当前从JSON映射的方式

我们有一个非常大的平面C#对象(20000ish属性),我们正在使用Newtonsoft JSON反序列化器将JSON对象反序列化到其中

由于反射,目前需要3分钟以上的时间

我们希望实现一个程序化的手动反序列化过程,以减少这段时间

我们已经阅读了大量有关这方面的参考资料,这些资料提供了如何进行手动反序列化的一般思路,但没有解释如何以编程方式进行反序列化

e、 g

例如,我们有一个具有20000个属性的大型购买对象,没有子类/对象属性,实际上是20000多个字符串。它们当前从JSON映射的方式是,我们在属性本身上有一个JSON属性,它对应于JSON本身上的属性


使用当前的方法进行反射非常慢,我们正在寻找一个正确的方向来推动如何以编程方式进行反射。

我不确定您的要求是什么。听起来您想使用JsonReader/JsonWriter方法,但不想手动将20000个JSON写入属性分配(例如,
if(token.Value==“prop1”)result.prop1=token.Value
)。如果是这种情况,那么您可以生成满足您需要的源代码,并将结果包含在项目中。有很多方法可以做到这一点。这里有一个方法:

using System;
using System.IO;
using System.Linq;
using System.Text;

namespace GetCustomAttribute
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            var sb = new StringBuilder();

            sb.AppendLine(@"
namespace GetCustomAttribute
{
    public static class PurchaseaOrderParser
    {
        public static void Parse(string jsonString, PurchaseOrder purchaseOrder)
        {

            var reader = new JsonTextReader(new StringReader(jsonString));

            var currentProperty = string.Empty;

            while (reader.Read())
            {
                if (reader.Value != null)
                {
                    if (reader.TokenType == JsonToken.PropertyName)
                        currentProperty = reader.Value.ToString();");

            var props = typeof(PurchaseOrder).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(IdAttribute)));
            foreach (var prop in typeof(PurchaseOrder).GetProperties())
            {
                var attribute = prop.GetCustomAttributes(typeof(IdAttribute), false).SingleOrDefault() as IdAttribute;
                if (attribute != null)
                {
                    var s = $"if (reader.TokenType == JsonToken.String && currentProperty == \"{attribute.Id}\") purchaseOrder.{prop.Name} = reader.Value.ToString();";
                    sb.AppendLine(s);
                }
            }

            sb.Append("}}}}}}");

            File.WriteAllText("PurchaseOrderParser.cs", sb.ToString());
        }
    }

    class PurchaseOrder
    {
        [Id("id")]
        public string Id { get; set; }

        [Id("name")]
        public string Name { get; set; }
    }

    class IdAttribute : Attribute
    {
        public string Id { get; set; }

        public IdAttribute(string id) => Id = id;
    }
}
产生:

namespace GetCustomAttribute
{
    public static class PurchaseaOrderParser
    {
        public static void Parse(string jsonString, PurchaseOrder purchaseOrder)
        {

            var reader = new JsonTextReader(new StringReader(jsonString));

            var currentProperty = string.Empty;

            while (reader.Read())
            {
                if (reader.Value != null)
                {
                    if (reader.TokenType == JsonToken.PropertyName)
                        currentProperty = reader.Value.ToString();
if (reader.TokenType == JsonToken.String && currentProperty == "id") purchaseOrder.Id = reader.Value.ToString();
if (reader.TokenType == JsonToken.String && currentProperty == "name") purchaseOrder.Name = reader.Value.ToString();
}}}}}}

.NET还包括生成运行时代码的功能。我对它们不熟悉,但您可以在运行时执行上述操作,这将确保解析器不会与
PurchaseOrder
类不同步;你试过了吗?是的,我们试过了,它产生的结果非常微小,只节省了大约5秒。问题更多的是反射,而不是大型对象堆。在链接的答案中没有反射。如果它只是一个具有一组字符串属性的单个对象,那么将其反序列化到
字典