问题
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