JsonResult equivalent to [DataMember(Name="Test")]
I have a method doing this:
public JsonResult Layar(string countryCode, string timestamp, string userId,
string developerId, string layarName, double radius,
double lat, double lon, double accuracy)
{
LayarModel model = new LayarModel(lat, lon, radius);
return Json(model, JsonRequestBehavior.AllowGet);
}
It returns this object:
public class LayarModel
{
private List<HotSpot> _hotSpots = new List<HotSpot>();
public List<HotSpot> HotSpots { get { return _hotSpots; } set { _hotSpots = value; } }
public string Name { get; set; }
public int ErrorCode { get; set; }
public string ErrorString { get; set; }
}
I want the JSON to be
{"hotspots": [{
"distance": 100,
"attribution": "The Location of the Layar Office",
"title": "The Layar Office",
"lon": 4884339,
"imageURL": http:\/\/custom.layar.nl\/layarimage.jpeg,
"line4": "1019DW Amsterdam",
"line3": "distance:%distance%",
"line2": "Rietlandpark 301",
"actions": 开发者_运维百科[],
"lat": 52374544,
"type": 0,
"id": "test_1"}],
"layer": "snowy4",
"errorString": "ok",
"morePages": false,
"errorCode": 0,
"nextPageKey": null
}
Everything comes out capitalised as in the class being returned (HotSpots
instead of hotspots
).
I have tried DataContract and DataMembers(Name="Test") but that doesn't work. Any suggestions?
JsonResult() uses JavaScriptSerializer internally for serialization, and it seems it doesn't support defining the serialized property names using attributes.
DataContractJsonSerializer supports this, so that may be a way to go.
Some links that may be useful:
- JavaScriptSerializer.Deserialize - how to change field names : JavaScriptSerializer.Deserialize - how to change field names
- DataContractJsonSerializer Versus JavaScriptSerializer : Changing Field Names: http://publicityson.blogspot.com/2010/06/datacontractjsonserializer-versus.html
I would also recommend installing json.NET but the rest is a lot easier. Below is an extension method I am using in my current application to provide better reuse, feel free to adapt it to your needs, but it should do what you need right out of the box.
public class JsonNetResult : ActionResult
{
public Encoding ContentEncoding { get; set; }
public string ContentType { get; set; }
public object Data { get; set; }
public JsonSerializerSettings SerializerSettings { get; set; }
public Formatting Formatting { get; set; }
public JsonNetResult()
{
SerializerSettings = new JsonSerializerSettings
{
//http://odetocode.com/blogs/scott/archive/2013/03/25/asp-net-webapi-tip-3-camelcasing-json.aspx
#if DEBUG
Formatting = Formatting.Indented, //Makes the outputted Json easier reading by a human, only needed in debug
#endif
ContractResolver = new CamelCasePropertyNamesContractResolver() //Makes the default for properties outputted by Json to use camelCaps
};
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = !string.IsNullOrEmpty(ContentType)
? ContentType
: "application/json";
if (ContentEncoding != null)
response.ContentEncoding = ContentEncoding;
if (Data != null)
{
JsonTextWriter writer = new JsonTextWriter(response.Output) {Formatting = Formatting};
JsonSerializer serializer = JsonSerializer.Create(SerializerSettings);
serializer.Serialize(writer, Data);
writer.Flush();
}
}
}
public static class JsonNetExtenionMethods
{
public static ActionResult JsonNet(this Controller controller, object data)
{
return new JsonNetResult() {Data = data};
}
public static ActionResult JsonNet(this Controller controller, object data, string contentType)
{
return new JsonNetResult() { Data = data, ContentType = contentType };
}
public static ActionResult JsonNet(this Controller controller, object data, Formatting formatting)
{
return new JsonNetResult() {Data = data, Formatting = formatting};
}
}
Here's an example of using it.
public JsonNetResult Layar(string countryCode, string timestamp, string userId,
string developerId, string layarName, double radius,
double lat, double lon, double accuracy)
{
LayarModel model = new LayarModel(lat, lon, radius);
return this.JsonNet(model);
}
The part to note that solves your problem specifically is when the ContractResolver
on the JsonSerializerSettings
is set to use new CamelCasePropertyNamesContractResolver()
This way you never have to set custom naming again.
精彩评论