非常简单的例子(我在单元测试中使用它):
private interface ISampleSubset
{
int id { get; }
}
private class Sample : ISampleSubset
{
public int id { get; set; }
public string name { get; set; }
}
这是NewtonSoft的JSON Serialize:
的小包装器public string Serialize<T>(T t)
{
using (var sw = new StringWriter())
{
using (var jw = new JsonTextWriter(sw))
{
var js = JsonSerializer.Create();
js.Serialize(jw, t);
jw.Flush();
}
return sw.GetStringBuilder().ToString();
}
}
现在我要序列化ISampleSubset: 并称之为:
ISampleSubSet t = new Sample()
{
id = 1,
name = "joe"
};
string json = Serialize(t);
我希望得到
{"id":1}
但我得到了
{"id":1,"name":"joe"}
我猜js.Serialize正在使用反射来“查看”界面对象“外部”的其他属性。如何将其限制为界面上的那些属性?
答案 0 :(得分:4)
序列化程序甚至不知道您的界面,因此它会为您提供所有内容 - 它接受object
,因此它不知道您已声明类型为ISampleSubset
的变量 - 它只知道对象本身是Sample
的一个实例。
可能不是最佳解决方案,但您可以使用JsonConverter
来限制序列化对象中显示的属性。
这段代码的效率可能非常低 - 请不要判断 - 只需把它放在一起,你可以清理细节并实现你需要的:
public class MyConverter<T> : JsonConverter {
private readonly string[] _propertyNames;
public MyConverter() {
_propertyNames = typeof(T).GetProperties().Select(p => p.Name).ToArray();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
var objectType = value.GetType();
var newObject = new Dictionary<string, object>();
foreach (string propName in _propertyNames) {
var prop = objectType.GetProperty(propName);
if (prop != null) {
newObject[propName] = prop.GetValue(value, null);
}
}
string s = JsonConvert.SerializeObject(newObject);
writer.WriteRaw(s);
}
public override bool CanConvert(Type objectType) {
return true; // ?
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
throw new NotImplementedException();
}
}
public static string Serialize<T>(T t) {
return JsonConvert.SerializeObject(t, new MyConverter<T>());
}
基本上它正在做的是使用接口类型的反射来检索它的属性,然后仅使用接口上找到的属性创建一个字典(你可以通过多种方式实现) - 然后使用简单的{{1} } class来序列化字典。
答案 1 :(得分:1)
NewtonSoft.JSON正在根据默认规则(从.NET 3.5 IIRC开始)序列化您创建的对象实例,该对象的所有属性都是默认可序列化的。如果将变量声明为接口类型并不重要,因为它可能通过反射进行序列化。
如果要限制序列化的属性,最好的方法是使用NonSerialized属性。