Mon problème est que je souhaite renvoyer les données JSON de camelCased (par opposition au PascalCase standard) via ActionResult s à partir de méthodes de contrôleur ASP.NET MVC, sérialisées par JSON.NET .
A titre d'exemple, considérons la classe C # suivante:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Par défaut, lors du renvoi d'une instance de cette classe à partir d'un contrôleur MVC en tant que JSON, celle-ci sera sérialisée de la manière suivante:
{
"FirstName": "Joe",
"LastName": "Public"
}
Je voudrais qu'il soit sérialisé (par JSON.NET) comme:
{
"firstName": "Joe",
"lastName": "Public"
}
Comment puis-je faire cela?
J'ai trouvé une excellente solution à ce problème sur le blog de Mats Karlsson. La solution consiste à écrire une sous-classe d'ActionResult qui sérialise les données via JSON.NET, en configurant ce dernier pour qu'il respecte la convention camelCase:
public class JsonCamelCaseResult : ActionResult
{
public JsonCamelCaseResult(object data, JsonRequestBehavior jsonRequestBehavior)
{
Data = data;
JsonRequestBehavior = jsonRequestBehavior;
}
public Encoding ContentEncoding { get; set; }
public string ContentType { get; set; }
public object Data { get; set; }
public JsonRequestBehavior JsonRequestBehavior { get; set; }
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (JsonRequestBehavior == JsonRequestBehavior.DenyGet && String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.");
}
var response = context.HttpContext.Response;
response.ContentType = !String.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
if (ContentEncoding != null)
{
response.ContentEncoding = ContentEncoding;
}
if (Data == null)
return;
var jsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
response.Write(JsonConvert.SerializeObject(Data, jsonSerializerSettings));
}
}
Puis utilisez cette classe comme suit dans votre méthode de contrôleur MVC:
public ActionResult GetPerson()
{
return new JsonCamelCaseResult(new Person { FirstName = "Joe", LastName = "Public" }, JsonRequestBehavior.AllowGet)};
}
ou simplement:
JsonConvert.SerializeObject(
<YOUR OBJECT>,
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
Par exemple:
return new ContentResult
{
ContentType = "application/json",
Content = JsonConvert.SerializeObject(new { content = result, rows = dto }, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }),
ContentEncoding = Encoding.UTF8
};
Je pense que c'est la réponse simple que vous recherchez. C'est tiré du blog de Shawn Wildermuth :
// Add MVC services to the services container.
services.AddMvc()
.AddJsonOptions(opts =>
{
opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
Une alternative au filtre personnalisé consiste à créer une méthode d'extension pour sérialiser tout objet en JSON.
public static class ObjectExtensions
{
/// <summary>Serializes the object to a JSON string.</summary>
/// <returns>A JSON string representation of the object.</returns>
public static string ToJson(this object value)
{
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Converters = new List<JsonConverter> { new StringEnumConverter() }
};
return JsonConvert.SerializeObject(value, settings);
}
}
Puis appelez-le quand vous revenez de l'action du contrôleur.
return Content(person.ToJson(), "application/json");
Dans ASP.NET Core MVC.
public IActionResult Foo()
{
var data = GetData();
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
return Json(data, settings);
}
Vous trouverez ci-dessous une méthode d'action qui renvoie une chaîne JSON (cameCase) en sérialisant un tableau d'objets.
public string GetSerializedCourseVms()
{
var courses = new[]
{
new CourseVm{Number = "CREA101", Name = "Care of Magical Creatures", Instructor ="Rubeus Hagrid"},
new CourseVm{Number = "DARK502", Name = "Defence against dark arts", Instructor ="Severus Snape"},
new CourseVm{Number = "TRAN201", Name = "Transfiguration", Instructor ="Minerva McGonal"}
};
var camelCaseFormatter = new JsonSerializerSettings();
camelCaseFormatter.ContractResolver = new CamelCasePropertyNamesContractResolver();
return JsonConvert.SerializeObject(courses, camelCaseFormatter);
}
Notez l'instance JsonSerializerSettings passée en tant que deuxième paramètre. C'est ce qui rend le camelCase arriver.
Plus simple, c'est mieux IMO!
Pourquoi ne fais-tu pas ça?
public class CourseController : JsonController
{
public ActionResult ManageCoursesModel()
{
return JsonContent(<somedata>);
}
}
Le contrôleur de classe de base simple
public class JsonController : BaseController
{
protected ContentResult JsonContent(Object data)
{
return new ContentResult
{
ContentType = "application/json",
Content = JsonConvert.SerializeObject(data, new JsonSerializerSettings {
ContractResolver = new CamelCasePropertyNamesContractResolver() }),
ContentEncoding = Encoding.UTF8
};
}
}
Vous devez définir les paramètres dans le fichier 'Startup.cs'
Vous devez également le définir dans les valeurs par défaut de JsonConvert, si vous souhaitez utiliser ultérieurement la bibliothèque directement pour sérialiser un objet.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddJsonOptions(options => {
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
}
J'ai fait comme ça:
public static class JsonExtension
{
public static string ToJson(this object value)
{
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
};
return JsonConvert.SerializeObject(value, settings);
}
}
c’est une méthode d’extension simple dans le noyau MVC, cela va donner la capacité ToJson () à chaque objet de votre projet. À mon avis, dans un projet MVC, la plupart des objets devraient pouvoir devenir json, bien sûr cela dépend :)