编程手动JSON反序列化为C#对象
我们有一个非常大的平面C#对象(20000ish属性),我们正在使用Newtonsoft JSON反序列化器将JSON对象反序列化到其中 由于反射,目前需要3分钟以上的时间 我们希望实现一个程序化的手动反序列化过程,以减少这段时间 我们已经阅读了大量有关这方面的参考资料,这些资料提供了如何进行手动反序列化的一般思路,但没有解释如何以编程方式进行反序列化 e、 g 例如,我们有一个具有20000个属性的大型购买对象,没有子类/对象属性,实际上是20000多个字符串。它们当前从JSON映射的方式是,我们在属性本身上有一个JSON属性,它对应于JSON本身上的属性编程手动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映射的方式
使用当前的方法进行反射非常慢,我们正在寻找一个正确的方向来推动如何以编程方式进行反射。我不确定您的要求是什么。听起来您想使用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秒。问题更多的是反射,而不是大型对象堆。在链接的答案中没有反射。如果它只是一个具有一组字符串属性的单个对象,那么将其反序列化到字典
?