¿Cómo puedo agregar un nodo raíz personalizado al serializar un objeto con JSON.NET?

He añadido una propiedad personalizada a algunos de mis objetos como este:

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

El atributo es muy simple:

 public class JsonCustomRoot :Attribute { public string rootName { get; set; } public JsonCustomRoot(string rootName) { this.rootName = rootName; } } 

La salida predeterminada de JSON.NET al serializar una instancia de un objeto es esta:

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

Ahora la pregunta es: ¿Cómo puedo agregar un nodo raíz a JSON con el valor del atributo personalizado de esta manera ?

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

He encontrado varios artículos que mencionan la interfaz de IContractResolver , pero no puedo entender cómo hacerlo. Mis bashs incluyen este pedazo de código sin terminar:

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

Aquí hay una solución específicamente para la API web, que también estoy usando: RootFormatter.cs

Lo escribí basado en Crear un formateador JSONP para la API web de ASP.NET .

En lugar de usar un atributo personalizado, estoy reutilizando el campo Título de JsonObjectAttribute . Aquí hay un código de uso:

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

Luego, agregue RootFormatter a su App_Start y regístrelo de la siguiente manera en WebApiConfig :

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

Pude obtener una respuesta envuelta similar a WebMessageBodyStyle.Wrapped de WCF:

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

¿Qué pasa si usas un objeto anónimo?

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

Una forma muy fácil de abordar esto es colocar el objeto dentro de otro objeto. tal vez fue demasiado simplista mirarlo, pero esto funciona cuando se trabaja con colecciones y objetos singulares.

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

Ahora, si coloca el StatusDTO dentro del objeto statusJsonModel y lo serializa como Json. Debería darte la respuesta deseada.

Tuve un reto similar en uno de mis proyectos. A continuación se muestra el paso que tomé para resolver el problema.

1. Mi clase de Entidad

 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. Creó otra clase, que se define en esta forma.

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

3. El controlador web API, que devolverá json.

  public HttpResponseMessage Products() { var kind = new KindOfMedia(); kind.Products = new List(); 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. Agregue esta línea de código a mi archivo de configuración WebApi en la carpeta App_Start

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

tenga en cuenta que Newtonsoft.Json.PreserveReferencesHandling.None , no conservará la referencia del tipo de serialización

El Json resultante es

 { "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" } ] }