C# 如何自定义JSON对象序列化?
我有一个ASP.NETRazor页面,其中我试图使用jQueryAjax请求显示日志列表。根据我在文档和论坛中的理解,我提出了以下ajax请求:C# 如何自定义JSON对象序列化?,c#,ajax,asp.net-mvc,entity-framework,json.net,C#,Ajax,Asp.net Mvc,Entity Framework,Json.net,我有一个ASP.NETRazor页面,其中我试图使用jQueryAjax请求显示日志列表。根据我在文档和论坛中的理解,我提出了以下ajax请求: $.ajax({ url: '@Url.Action("GetLogs","Logs")', dataType: "json", contentType :"application/json; charset=utf-8", success: function (data) { console.log("
$.ajax({
url: '@Url.Action("GetLogs","Logs")',
dataType: "json",
contentType :"application/json; charset=utf-8",
success: function (data) {
console.log("success");
console.log(data);
},
error: function (msg) {
console.log("error");
console.log(msg);
}
});
这是可行的,但是它返回的json并不是我想要的。以下是ajax请求和getAllLogs函数调用的控制器代码:
- LogsController -
public JsonResult GetLogs()
{
List<Log> _loglist = LogsModel.getAllLogs(UserModel.getUser(Session["FirstName"].ToString(), Session["LastName"].ToString()));
String json = JsonConvert.SerializeObject(_loglist, Formatting.Indented, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
return Json(json, JsonRequestBehavior.AllowGet);
}
- LogsModel -
//get all logs to display in admin tab
public static List<Log> getAllLogs(User _user)
{
// if user is admin we can show logs concerning all users
if(UserModel.isAdmin(_user))
return db.Logs.Where(log => log.Action.Equals("Set Characteristic")).OrderByDescending(log => log.Id).ToList();
else
//user is manager and will see only users in same plant
return db.Logs.Where(log => log.User.Plant.Code.Equals(_user.Plant.Code) && log.Action.Equals("Set Characteristic")).OrderByDescending(log => log.Id).ToList();
}
首先,我设计了数据库,用户对象与日志一起返回,因此返回的是Json:
[
{
"User": {
"Characteristic_Value": [],
"Logs": [
{
"Id": 1,
"User_Id": 1,
"Date": "2014-08-11T14:11:52.523",
"Action": "Login attempt",
"State": true,
"Message": "User successfully logged in"
},
{
"Id": 2,
"User_Id": 1,
"Date": "2014-08-11T14:13:45.07",
"Action": "Login attempt",
"State": true,
"Message": "User successfully logged in"
},
{
"Id": 3,
"User_Id": 1,
"Date": "2014-08-11T14:15:07.043",
"Action": "Login attempt",
"State": true,
"Message": "User successfully logged in"
},
Other User Data ...
},
"Id" : 21,
"User_Id": 1,
"Date": "2014-08-11T10:00:00.000",
"Action": "Set Characteristic",
"State": true,
"Message" : "User changed characteristic [charac_name]"
}
]
我得到了所有的用户数据。我是唯一一个在这个项目上工作的人,所以现在获取数据不需要很长时间,但在不久的将来,将有更多的用户,需要查询的数据量将永远不会停止增加,我非常担心响应时间
所以最后我的问题是:是否有可能删除随日志返回的用户数据
我仍然对JsonSerializerSettings感到困惑,但也许这就是解决这个问题的方法?我认为您有两种选择: 将不希望序列化的属性标记为[JsonIgnore]。如果您的日志类位于一个真正不应该关心JSON序列化的不同层,那么这可能不是一个很好的选择 创建以表示确实要发送的信息,可以选择使用AutoMapper之类的工具将类映射到一起 例如,LogViewModel可能如下所示:
public class LogViewModel
{
public int Id { get; set; }
public int User_Id { get; set; }
public DateTime Date { get; set; }
public string Action { get; set; }
public bool State { get; set; }
public string Message { get; set; }
}
然后,您应该调整代码以序列化一组LogViewModels:
IEnumerable<LogViewModel> viewModels =
_logList.Select(l => new LogViewModel
{
Id = l.Id,
User_Id = l.User_Id
/* etc. */
});
String json = JsonConvert.SerializeObject(viewModels);
上面的映射代码可能会变得单调乏味,这就是像这样的工具的用武之地
您也可以只投影一个匿名类型,其中包含您关心的属性,效果类似,但是我发现管理ViewModels要容易得多
我建议您选择ViewModel路线,尤其是当人们在系统的这个特定区域添加您不关心的属性时,它可以很好地分离关注点并保护您免受问题的困扰。为什么不在linq中选择日志?我不确定您的意思。但我想这就是我在getAllLogs函数中所做的。对于实体框架,因为我在指向用户表的日志中有一个foreignkey,对于我得到的每个日志,我都会得到所有的用户信息。我不确定我能不能解释清楚。我没有日志类,每个类都是base中的表,所以我不能使用注释。2.我要试试这个:它来自于漫游论坛之类的东西,但我并不真正理解它,我认为ViewModels与MVCViewModels不兼容。它们只是一种模式,在ASP.NET MVC中被广泛使用。它们与MVVM中ViewModel的含义不同,虽然我刚刚安装了automapper并创建了LogsViewModel,而且效果非常好:非常感谢@尼迪文:没问题!很乐意帮忙。
IEnumerable<LogViewModel> viewModels =
_logList.Select(l => new LogViewModel
{
Id = l.Id,
User_Id = l.User_Id
/* etc. */
});
String json = JsonConvert.SerializeObject(viewModels);