在使用JSON.NET序列化对象时,如何添加自定义根节点?

Esp*_*spo 14 c# serialization json custom-attributes json.net

我已经为我的一些对象添加了一个自定义属性,如下所示:

[JsonCustomRoot("status")]
public class StatusDTO 
{
    public int StatusId { get; set; }
    public string Name { get; set; }
    public DateTime Created { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

属性非常简单:

public class JsonCustomRoot :Attribute
{
    public string rootName { get; set; }

    public JsonCustomRoot(string rootName)
    {
        this.rootName = rootName;
    }
}
Run Code Online (Sandbox Code Playgroud)

序列化对象实例时JSON.NET的默认输出是:

{"StatusId":70,"Name":"Closed","Created":"2012-12-12T11:50:56.6207193Z"}
Run Code Online (Sandbox Code Playgroud)

现在的问题是:如何使用自定义属性的值向JSON添加根节点,如下所示:

{status:{"StatusId":70,"Name":"Closed","Created":"2012-12-12T11:50:56.6207193Z"}}
Run Code Online (Sandbox Code Playgroud)

我发现有几篇提到IContractResolver接口的文章,但我无法理解如何做到这一点.我的尝试包括这段未完成的代码:

protected override JsonObjectContract CreateObjectContract(Type objectType)
{
    JsonObjectContract contract = base.CreateObjectContract(objectType);

    var info = objectType.GetCustomAttributes()
                   .SingleOrDefault(t => (Type)t.TypeId==typeof(JsonCustomRoot));
    if (info != null)
    {
        var myAttribute = (JsonCustomRoot)info;
        // How can i add myAttribute.rootName to the root from here?
        // Maybe some other method should be overrided instead?
    }

    return contract;
}
Run Code Online (Sandbox Code Playgroud)

Bud*_*hiP 8

如果您使用匿名对象怎么办?

JSON.Serialize(new { status = targetObject});
Run Code Online (Sandbox Code Playgroud)

  • 我在.NET 4.0 WebAPI项目中使用JSON.Net作为序列化程序,所以我试图避免在返回数据时编写自定义代码.我希望在应用属性时为我完成它. (4认同)

Eug*_*ota 5

这是一个专门针对Web API的解决方案,我也在使用它:RootFormatter.cs

我是基于为ASP.NET Web API创建JSONP Formatter而编写的.

我没有使用自定义属性,而是重用了Title字段JsonObjectAttribute.这是一个使用代码:

using Newtonsoft.Json

[JsonObject(Title = "user")]
public class User
{
    public string mail { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后,将RootFormatter添加到App_Start并按如下方式注册WebApiConfig:

GlobalConfiguration.Configuration.Formatters.Insert(0, new RootFormatter());
Run Code Online (Sandbox Code Playgroud)

我得到了一个类似于WCF的包装响应WebMessageBodyStyle.Wrapped:

{"user":{
  "mail": "foo@example.com"
}}
Run Code Online (Sandbox Code Playgroud)

  • 这真的很酷!如果它有一个收藏解决方案,那将是史诗般的. (2认同)

小智 5

解决这个问题的一个非常简单的方法是将对象放置在另一个对象内。看待它可能过于简单化,但这在处理集合和单个对象时是有效的。

  public class StatusDTO
    {
        public int StatusId { get; set; }
        public string Name { get; set; }
        public DateTime Created { get; set; }
    }

    public class statusJasonModel
    {
        public StatusDTO status { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

现在,如果将 StatusDTO 放入 statusJsonModel 对象并将其序列化为 Json。它应该会给你你想要的答案。