如何在序列化为不涉及属性的json时忽略属性

时间:2011-07-27 22:49:46

标签: c# json entity-framework-4

我正在使用Entity Framework来生成我的模型。我想通过JSON传达其中一些模型。问题是我不希望EF对模型进行序列化的东西(EntityKey,EntityState和所有EntityCollection<>属性)

由于EF生成这些模型,因此使用ScriptIgnore或类似方法来修饰属性并不可行。

有没有办法让任何json序列化程序序列化一个对象并让它忽略不需要我更改模型源代码的字段? (我可以添加模型,但是,如果它有帮助,因为它们被声明为部分类)

3 个答案:

答案 0 :(得分:1)

我刚刚遇到类似问题,在这种情况下,它是Linq to SQL模型上的自定义对象属性,我宁愿只是串行进出数据库而不是设置大量额外的字段和额外的构造函数。我不确定这与你的情况有多接近,但它应该具有适应性。

我见过的大多数解决方案都希望包含属性(由于自动代码生成而不可能)或滚动自定义转换器(过度杀伤,特别是如果你想捕获嵌套对象等)。

我的想法是,由于LinqToSql,我不想要的所有属性都已经被赋予了属性,所以不是手动获取我想要的属性,而是尝试序列化它们,首先是序列化,然后是DeSerialize。这为您提供了更容易使用的对象图,并且您已完成所有嵌套。

接下来获取我们不想要的成员名称。你如何得到这些取决于你,甚至可能是手动给它命名的方式,就像你从MVC中的模型绑定中排除一样。在我的例子中,一些Linq和一些反射让我们获得了Linq to SQL生成的所有属性的名称。

由于我们的对象是一个简单的Dictonary,我们遍历我们不需要的成员并将其从字典中删除。

最后再次序列化你的词典。

public string JsonMinusProperties(object toSerialize)
    {
        //Replace this with your preferred way of getting your unwanted properties
        var LinqMemberNames = toSerialize.GetType().GetProperties().Where(y=>
            y.GetCustomAttributes(true).Any(x =>
                x.GetType().Namespace == "System.Data.Linq.Mapping"
            )
        ).Select(x=>x.Name);

        JavaScriptSerializer js = new JavaScriptSerializer();
        string json = js.Serialize(toSerialize);
        var tempobj = js.DeserializeObject(json) as Dictionary<string, object>;
        foreach (string linqMember in LinqMemberNames)
        {
            tempobj.Remove(linqMember);
        }
        return js.Serialize(tempobj);
    }

这只会从第一级删除,但如果需要删除更深层的属性,原则上应该很容易走字典。

答案 1 :(得分:0)

如果您使用DataContractJsonSerializer序列化为JSON,那么它将仅序列化具有[DataMember]属性的属性。

要考虑的另一个选项是为要在JSON中公开的数据设置单独的DTO对象。该对象将从您的实体模型构建。这种方法的好处是你有一个显式的类,DTO,它定义数据契约,并与底层实体模型分离。

答案 2 :(得分:0)

JayRock中,您可以创建自己的IExporter。基本形式可能如下所示:

class FooExporter : IExporter
{
    public void Export(ExportContext context, object value, JsonWriter writer)
    {
        var properties = value.GetType().GetProperties();

        writer.WriteStartObject();

        foreach (var property in properties)
        {
            var propertyValue = property.GetValue(value, null);
            if (!JsonNull.LogicallyEquals(propertyValue))
            {
                writer.WriteMember(property.Name);
                context.Export(propertyValue, writer);
            }
        }

        writer.WriteEndObject();
    }

    public Type InputType
    {
        get { return typeof(Foo); }
    }
}

您可以按照您想要的任何方式修改它(例如,忽略具有特定名称的所有属性;在构造函数中采用具体类型)。然后你可以像这样使用它:

var context = JsonConvert.CurrentExportContextFactory();
context.Register(new FooExporter());
// always use this context
JsonConvert.CurrentExportContextFactory = () => context;
string json = JsonConvert.ExportToString(new Foo { … });

另一种选择是在您的实体中实施IJsonExportable。它有一个Export()方法,与上面的方法非常相似。