【问题标题】:Fast, dynamic one way JSON serialization for .Net.Net 的快速、动态的单向 JSON 序列化
【发布时间】:2013-07-07 15:46:10
【问题描述】:

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

  1. 我无法使用外部库。我的项目本身就是一个库,我不能引入依赖项。
  2. 序列化必须是一种方式。即我的 .Net 对象将没有任何设置器。这是因为无法将部分数据从 JSON 序列化回托管对象。
  3. 它必须是动态的。某些要序列化的类型要到运行时才能知道。
  4. 出于显而易见的原因,它必须很快。我考虑过使用反射并手动进行序列化,但我害怕时间损失。

【问题讨论】:

  • 您的第三个和第四个要求不能合并。为了动态,它必须使用反射,而且速度不会很快。
  • 我作为 .Net 消费者使用的反射与通过 DataContract 序列化或 ISerializable 中的非反射分析执行的反射之间存在差异

标签: c# .net json serialization datacontractjsonserializer


【解决方案1】:

您的问题似乎非常广泛,并邀请人们为您提供现成的解决方案。我不会那样做,但我可以给你一些关于解决 3 vs 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/ 公开提供

祝你好运。

【讨论】:

  • 这就是 C# 很棒的原因! +1
  • 讽刺的定义:我从未考虑过使用表达式树,即使要序列化的大部分数据都是表达式树:)。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-07
  • 2017-05-10
  • 2013-05-04
  • 2011-07-27
  • 1970-01-01
  • 2015-02-03
相关资源
最近更新 更多