3

非常简单的示例(我在单元测试中使用它):

    private interface ISampleSubset
    {
        int id { get; }
    }

    private class Sample : ISampleSubset
    {
        public int id { get; set; }
        public string name { get; set; }
    }

这是一个围绕 NewtonSoft 的 JSON 序列化的小包装器:

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 正在使用反射来“查看”接口“外部”对象上的其他属性。如何将其限制为界面上的那些属性?

4

2 回答 2

4

序列化器甚至不知道你的接口,所以它给了你一切——它接受一个object,所以它不知道你已经声明了你的类型变量ISampleSubset——它只知道对象本身是一个Sample.

可能不是最好的解决方案,但您可以使用 aJsonConverter来限制出现在序列化对象中的属性。

这段代码可能效率很低 - 请不要判断 - 只是把它放在一起,你可以清理细节并根据需要实现:

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>());
}

基本上它所做的是使用接口类型上的反射来检索其属性,然后仅使用在接口上找到的属性创建一个字典(您可以通过多种方式做到这一点) - 然后使用简单的JsonConvert类来序列化字典。

于 2013-05-24T15:10:30.400 回答
1

NewtonSoft.JSON 根据默认规则(从 .NET 3.5 IIRC 开始)对您创建的对象实例进行序列化,即默认情况下对象的所有属性都是可序列化的。是否将变量声明为接口类型并不重要,因为它可能通过反射进行序列化。

如果要限制被序列化的属性,最好的方法是使用NonSerialized属性。

于 2013-05-24T14:56:06.937 回答