Asp.net mvc 如何将某些公共属性从序列化为JsonResult中排除?
我有一个自定义viewmodel,它使用JsonResult进行序列化。ViewModel有一些属性必须是公共的,但同时这些属性在生成的Json输出中不应可见 我已经尝试使用[NonSerialized]属性,但似乎没有任何效果Asp.net mvc 如何将某些公共属性从序列化为JsonResult中排除?,asp.net-mvc,json,serialization,Asp.net Mvc,Json,Serialization,我有一个自定义viewmodel,它使用JsonResult进行序列化。ViewModel有一些属性必须是公共的,但同时这些属性在生成的Json输出中不应可见 我已经尝试使用[NonSerialized]属性,但似乎没有任何效果 有什么简单的方法可以做到这一点吗?或者我必须为自己的结果类型编写代码(在这种情况下,我可能不会麻烦)?这不是您想要的答案,但您可以使用以下代码和匿名类来欺骗Json(): MyModel model = ...; return Json(new MyModel {mod
有什么简单的方法可以做到这一点吗?或者我必须为自己的结果类型编写代码(在这种情况下,我可能不会麻烦)?这不是您想要的答案,但您可以使用以下代码和匿名类来欺骗
Json()
:
MyModel model = ...;
return Json(new MyModel {model.Prop1, model.Prop2});
您可以创建一个包装器类,该类只公开您想要在JsonResult中显示的那些属性。在下面的示例中,Cow有两个属性——“Leg”和“Moo”。假设您只想将“Leg”作为属性公开。然后 尺寸cw为整流罩=新整流罩(c) 将返回一个仅公开“Leg”的包装器类。如果您只想显示某些属性子集,这对于DataGridView之类的东西也很有用 公营母牛 作为字符串的公共只读属性Leg()
get
return "leg"
end get
get
return "moo"
end get
get
return m_cow.Leg()
end get
端属性
作为字符串的公共只读属性Moo()
get
return "leg"
end get
get
return "moo"
end get
get
return m_cow.Leg()
end get
端属性
末级
公共类牛仔装
Private m_cow as Cow = Nothing
Public Sub New(ByVal cow as Cow)
m_cow = cow
end Sub
m_cow = cow
作为字符串的公共只读属性Leg()
get
return "leg"
end get
get
return "moo"
end get
get
return m_cow.Leg()
end get
端属性
结束类扩展该类,使其不包括具有非序列化数据属性的属性
。然后,您可以创建一个自定义的ActionResult
,它使用JavaScriptConverter
来序列化对象
这将创建一个可靠且可测试的类,而无需(重新)生成包装器类或使用匿名对象。看看James Newton King。它将满足您的需要。您可以在不应序列化的成员上添加
[ScriptIgnore]
属性。请参阅以获取示例。只需创建一个要返回的接口,而不是类
public interface IMyViewModel {
string MyPublicProperty { get; set; }
}
然后创建一个继承接口的类
public class MyViewModel : IMyViewModel {
public string MyPublicProperty { get; set; }
public string MyNotSoPublicProperty { get; set; }
}
并在控制器操作中返回接口,而不是类
public JsonResult MyJson(){
IMyViewModel model = new MyViewModel();
return Json(model);
}
生成的JSON将是
{
'MyPublicProperty': ''
}
客户端脚本编写的挑战之一是,如果要更改类,则不知道是否要破坏客户端实现。如果您在JSON中使用接口类型,您就会明白,如果您更改接口,您正在做的事情可能会扼杀客户端实现。而且,如果您正在更改某些不在接口中的内容(因此未被序列化),它还可以避免徒劳地重复检查客户端
而且,很多时候,ViewModels中可能包含大型集合或复杂类型,您不一定要将其输出到客户端。序列化或公开不属于客户机代码的信息可能需要很长时间。使用接口将使了解输出中的内容更加透明
此外,在属性上使用[ScriptIgnore]等属性仅适用于特定场景(JavaScript序列化),例如,如果以后要序列化为XML,则会面临完全相同的问题。这将不必要地为ViewModel添加大量属性。你到底想要多少?使用intefaces适用于任何地方,并且viewmodel不需要添加额外的属性。我知道我可以使用匿名类型。但这使得单元测试结果更加困难。这意味着我要么必须解析序列化结果,要么使用反射。单元测试JsonResults很难开始。你以前是怎么做的?看起来您无法检索驱动JsonResult的底层模型,这一点都没有问题。Data属性包含要序列化的对象。因为我使用的是自定义viewmodel而不是匿名对象类型,所以我可以简单地获取该对象并测试其属性。虽然很痛苦,但您可以创建新版本的类,并简单地复制所需的属性。我用这种方法编辑了我的文章。@Adrian:谢谢,我不知道数据引用了序列化对象。这是可行的,但代价是必须复制很多属性,所以这不是我真正想要的。代价是什么?编程?在类文件作为输入的情况下,编写一个简单的实用程序来构造这些类,或者编写一个可以使用内省动态构造属性的类应该很简单。运行时间?额外引用的代价是可以忽略的。我不知道你的意思是通过反射在运行时构造这样的类型。这当然涵盖了我的所有自定义viewmodel类型,而无需任何额外的编码。这是一种有效的方法,但与使用现成工具(即Json.Net)相比太复杂了。太棒了!(有现成的工具)。我应该写“它应该是可能的”而不是“它应该是简单的”。。因为我自己对内省知之甚少。在用LINQ to SQL类填充DataGridView时,我使用了包装类(硬编码,不使用内省)。通常我不想显示表中的所有字段,所以包装器会处理这个问题。这也是我想到的方法。这当然是可行的,但因为这只是为了节省每个Json请求的几个字节,所以我希望有更简单的方法。很好的方法,但与我的案例相比,工作太多了。太完美了!事实证明,James还编写了一个匹配的JsonResult类型:对于其他类型,该属性的完整名称空间是[System.Web.Script.Serialization.ScriptIgnore],在使用常规MVC
return Json()时,它看起来像ScriptIgnore
)
---然后JsonIgnore
如果使用Json.NET
大多数答案都是使用Attribute或wrapper。我只想简单地排除s