How can I add a custom root node when serializing an object with JSON.NET?

孤者浪人 提交于 2019-11-27 01:53:53

问题


I have added a custom property to some of my objects like this:

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

The attribute is very simple:

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

    public JsonCustomRoot(string rootName)
    {
        this.rootName = rootName;
    }
}

The default output from JSON.NET when serializing an instance of an object is this:

{"StatusId":70,"Name":"Closed","Created":"2012-12-12T11:50:56.6207193Z"}

Now the question is: How can I add a root-node to the JSON with the value of the custom attribute like so:

{status:{"StatusId":70,"Name":"Closed","Created":"2012-12-12T11:50:56.6207193Z"}}

I have found several articles mentioning the IContractResolver interface, but I cannot grasp how to do it. My attempts include this unfinished piece of code:

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;
}

回答1:


Here's a solution specifically for Web API, which I am also using: RootFormatter.cs

I wrote it based on Creating a JSONP Formatter for ASP.NET Web API.

Instead of using a custom attribute I am reusing Title field of JsonObjectAttribute. Here's a usage code:

using Newtonsoft.Json

[JsonObject(Title = "user")]
public class User
{
    public string mail { get; set; }
}

Then, add RootFormatter to your App_Start and register it as follows in WebApiConfig:

GlobalConfiguration.Configuration.Formatters.Insert(0, new RootFormatter());

I was able to get a wrapped response similar to WCF's WebMessageBodyStyle.Wrapped:

{"user":{
  "mail": "foo@example.com"
}}



回答2:


What if you use an anonymous object?

JSON.Serialize(new { status = targetObject});



回答3:


A very easy way of approaching this is to place the object inside another object. it maybe a over simplistic was of looking at it, but this works when working with collections, and singular objects.

  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; }
    }

Now you if you put the StatusDTO inside the statusJsonModel object and serialize it as Json. It should give you your desired answer.




回答4:


I had similar challenge in one of my project. Below is the step that I took in resolving the problem.

1. My Entity class

public class Product
    {
        [Key]
        public string Id { get; set; }
        public string Title { get; set; }
        public string Album { get; set; }
        public string Artist { get; set; }
        public string Genre { get; set; }

    }

2. Created another Class, which is defined in this form.

    public class KindOfMedia
        {
            public KindOfMedia()
            {
                Product = new List<Product>();
            }
            public List<Product> Product { get; set; }
        }

3. The Web API controller, that will return json

            public HttpResponseMessage Products()
            {
                var kind = new KindOfMedia();
                kind.Products = new List<Product>();
                kind.Products.Add(new Product
                {
                    Id = Guid.NewGuid().ToString(),
                    Title = "I am A Winner",
                    Album = "",
                    Artist = "Project Fame",
                    Genre = "Contemporal"                
                });
                kind.Products.Add(new Product
                {
                    Id = Guid.NewGuid().ToString(),
                    Title = "Great Nation",
                    Album = "Oceans",
                    Artist = "Timi Dakolo",
                    Genre = "Gospel"
                });

                return Request.CreateResponse(HttpStatusCode.OK, kind);
            }

4. Add this line of code to my WebApi Config file in App_Start folder

     var json = config.Formatters.JsonFormatter;
                json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;

please note that Newtonsoft.Json.PreserveReferencesHandling.None, will not preserve reference of the serialize type

The resulting Json is

{
  "Musics": [
    {
      "Id": "bf9faeee-7c39-4c33-a0ea-f60333604061",
      "Title": "I am A Winner",
      "Album": "",
      "Artist": "Project Fame",
      "Genre": "Contemporal"
    },
    {
      "Id": "243edd32-7ba2-4ac4-8ab9-bba6399cb0a6",
      "Title": "Great Nation",
      "Album": "Oceans",
      "Artist": "Timi Dakolo",
      "Genre": "Gospel"
    }
  ]
}


来源:https://stackoverflow.com/questions/13839426/how-can-i-add-a-custom-root-node-when-serializing-an-object-with-json-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!