c# - C# 对象到 JSON 的模板化序列化

标签 c# .net json

我需要将对象序列化为 JSON。我想用 template 来完成它,而不是使用数据注释(就像大多数框架那样)。有人知道这样做的好方法吗?

一张图片胜过1000个字。我正在寻找看起来像这样的东西:

enter image description here

例如,如果我有这样一个类:

public class Test  
{ 
    public string Key { get; set; } 
    public string Name { get; set; } 
    public string Code { get; set; } 
    public Test Related { get; set; } 
} 

还有一个模板字符串可能如下所示:

{ 
    id: "$Key",
    name: "$Name",
    related: "$Related.Name"
}

我想获取一个JSON对象,其属性根据对象的KeyNameRelated.Name填写。

基本上,我正在寻找一种支持模板JSON 序列化方法。

最佳答案

我不知道有哪个库可以为您做这件事,但是您自己构建它并不难。

如果您有自己的模板,则需要将其解析为 JSON,然后将所有占位符替换为实际值。为此,您可以使用访问者模式。

由于 JSON.NET(我正在使用的 JSON 库)似乎没有访问者,您可以自己创建一个:

abstract class JsonVisitor
{
    public virtual JToken Visit(JToken token)
    {
        var clone = token.DeepClone();
        return VisitInternal(clone);
    }

    protected virtual JToken VisitInternal(JToken token)
    {
        switch (token.Type)
        {
        case JTokenType.Object:
            return VisitObject((JObject)token);
        case JTokenType.Property:
            return VisitProperty((JProperty)token);
        case JTokenType.Array:
            return VisitArray((JArray)token);
        case JTokenType.String:
        case JTokenType.Integer:
        case JTokenType.Float:
        case JTokenType.Date:
        case JTokenType.Boolean:
        case JTokenType.Null:
            return VisitValue((JValue)token);
        default:
            throw new InvalidOperationException();
        }
    }

    protected virtual JToken VisitObject(JObject obj)
    {
        foreach (var property in obj.Properties())
            VisitInternal(property);

        return obj;
    }

    protected virtual JToken VisitProperty(JProperty property)
    {
        VisitInternal(property.Value);

        return property;
    }

    protected virtual JToken VisitArray(JArray array)
    {
        foreach (var item in array)
            VisitInternal(item);

        return array;
    }

    protected virtual JToken VisitValue(JValue value)
    {
        return value;
    }
}

然后创建一个用实际值替换占位符的专用访问器:

class JsonTemplateVisitor : JsonVisitor
{
    private readonly object m_data;

    private JsonTemplateVisitor(object data)
    {
        m_data = data;
    }

    public static JToken Serialize(object data, string templateString)
    {
        return Serialize(
            data, (JToken)JsonConvert.DeserializeObject(templateString));
    }

    public static JToken Serialize(object data, JToken template)
    {
        var visitor = new JsonTemplateVisitor(data);

        return visitor.Visit(template);
    }

    protected override JToken VisitValue(JValue value)
    {
        if (value.Type == JTokenType.String)
        {
            var s = (string)value.Value;

            if (s.StartsWith("$"))
            {
                string path = s.Substring(1);

                var newValue = GetValue(m_data, path);

                var newValueToken = new JValue(newValue);

                value.Replace(newValueToken);

                return newValueToken;
            }
        }

        return value;
    }

    private static object GetValue(object data, string path)
    {
        var parts = path.Split('.');

        foreach (var part in parts)
        {
            if (data == null)
                break;

            data = data.GetType()
                .GetProperty(part)
                .GetValue(data, null);
        }

        return data;
    }
}

使用起来就很简单了。例如,使用以下模板:

{ 
    id : "$Key",
    name: "$Name",
    additionalInfo:
    {
        related: [ "$Related.Name" ]
    }
}

您可以使用这样的代码:

JsonTemplateVisitor.Serialize(data, templateString)

结果是这样的:

{
  "id": "someKey",
  "name": "Isaac",
  "additionalInfo": {
    "related": [
      "Arthur"
    ]
  }
}

您可能想要添加一些错误检查,但除此之外,代码应该可以工作。此外,它使用反射,因此如果性能很重要,它可能不适合。

关于c# - C# 对象到 JSON 的模板化序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9174540/

相关文章:

c# - .net 4.0 中的 MemoryCache 与 ObjectCache 有什么区别?

.net - 在哪里使用工作单元模式验证我的实体?

javascript - 调用 MVC Controller 操作以返回 Wordpress 网站的 View

c# - 已内联的函数的堆栈跟踪是否在抛出的异常中保留?

.net - 我什么时候应该在 WPF 4.0 中使用 SnapsToDevicePixels?

c# - 存储对结构数组的 C# 引用并检索它 - 可以不复制吗?

.net - ASP.NET MVC 4 WebAPI PostAsJsonAsync Newtonsoft.Json 错误

jquery - 使用 jQuery 将选择列表转换为 JSON

c# - 如何从函数中的选择查询返回 int 值?

c# - 为 asmx WebService 抛出 405 的自定义错误处理程序