用于.Net的快速、动态的单向JSON序列化

本文关键字:JSON 动态 序列化 Net 用于 | 更新日期: 2023-09-27 18:21:28

我想实现从CLR对象到JSON字符串的序列化,但我有以下限制:

  1. 我不能使用外部图书馆。我的项目本身就是一个库,我不能引入依赖项
  2. 序列化必须是一种方式。即,我的.Net对象将没有任何setter。这是因为不可能将JSON中的一些数据序列化回托管对象
  3. 它必须是动态的。要序列化的某些类型要到运行时才能知道
  4. 它一定很快,原因很明显。我曾考虑过使用反射和手动进行序列化,但我担心会造成时间损失

用于.Net的快速、动态的单向JSON序列化

您的问题似乎非常广泛,并邀请人们为您提供现成的解决方案。我不会这么做,但我可以给你一些关于解决3对4 问题的提示

以下是一些将任意类型的对象读取到键值对集合中的基本代码:

void Main()
{
    var reader = CreateReader(typeof(Foo));
    reader(new Foo { Bar = "BARRRRR", Baz = 123 }).Dump();
}
public class Foo
{
    public string Bar {get; set;}
    public int Baz {get; set;}
}

static ConstructorInfo Ctor = typeof(KeyValuePair<string, object>).GetConstructor(new Type[] { typeof(String), typeof(Object) });
static Func<object, IEnumerable<KeyValuePair<string, object>>> CreateReader(Type t)
{
    var prm = Expression.Parameter(typeof(Object), "prm");
    var obj = Expression.Variable(t, "obj");
    var arr = new List<Expression>();
    foreach (var p in t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        arr.Add(Expression.New(Ctor, Expression.Constant(p.Name), Expression.Convert(Expression.Property(obj, p), typeof(Object))));
    }
    var body = Expression.Block(
        typeof(IEnumerable<KeyValuePair<string, object>>),
        new ParameterExpression[] { obj },
        Expression.Assign(obj, Expression.Convert(prm, t)),
        Expression.NewArrayInit(typeof(KeyValuePair<string, object>), arr)
    );
    return Expression.Lambda<Func<object, IEnumerable<KeyValuePair<string, object>>>>(body, prm).Compile();
}

这允许您创建一个读取器委托,它与任何静态编译的代码一样快速高效。这应该会给你足够的方向,让你把它带到你想用它做的任何事情上

接下来的步骤将是创建所有管道:

  1. 递归遍历要序列化的对象树
  2. 创建和/或缓存读卡器
  3. 读取键值对并将其写入JSON

这些都是琐碎的任务,你应该照顾好自己。JSON规范公开于http://json.org/

祝你好运。