4

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?

p.campbell
  • 98,673
  • 67
  • 256
  • 322
Andy
  • 305
  • 1
  • 4
  • 14

2 Answers2

1

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:

Community
  • 1
  • 1
CGK
  • 2,662
  • 21
  • 24
0

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.

Nick Albrecht
  • 16,607
  • 10
  • 66
  • 101