如何限制NewtonSoft.JSON序列化接口?

时间:2013-05-24 14:45:27

标签: json json.net

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

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

2 个答案:

答案 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属性。