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

C# 序列化为不涉及属性的json时如何忽略属性,c#,json,entity-framework-4,C#,Json,Entity Framework 4,我正在使用实体框架生成模型。我想通过JSON与这些模型中的一些进行通信。问题是我不希望EF附加到模型上的内容被序列化(EntityKey、EntityState和所有EntityCollection属性) 由于EF生成这些模型,因此用ScriptIgnore或类似的东西来装饰属性实际上是不可行的 对于任何json序列化程序,有没有一种方法可以序列化一个对象并让它忽略不需要我更改模型源的字段?(不过,我可以添加到模型中,如果有帮助的话,因为它们被声明为分部类)如果您使用序列化到JSON,那么它将只

我正在使用实体框架生成模型。我想通过JSON与这些模型中的一些进行通信。问题是我不希望EF附加到模型上的内容被序列化(EntityKey、EntityState和所有EntityCollection属性)

由于EF生成这些模型,因此用ScriptIgnore或类似的东西来装饰属性实际上是不可行的

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

如果您使用序列化到JSON,那么它将只序列化具有[]属性的属性

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

在中,您可以创建自己的
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 { … });
您可以按任何方式修改它(例如,忽略具有特定名称的所有属性;在构造函数中使用具体类型)。然后您可以这样使用它:

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()
方法,与上面的方法非常相似。

我刚刚遇到了一个类似的问题,在这种情况下,它是Linq-to-SQL模型上的一个自定义对象属性,我更愿意在数据库中进行序列化,而不是设置大量额外的字段和额外的构造函数。我不确定这与你的情况有多接近,但它应该是可适应的

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

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

接下来,获取我们不需要的成员名称。如何获得这些信息取决于您,甚至可能需要手动为其命名,就像您在MVC中排除模型绑定一样。在我的例子中,通过一点Linq和一点反射,我们可以得到LINQtoSQL生成的所有属性的名称

因为我们的对象是一个简单的口述词,所以我们迭代不需要的成员,并将它们从字典中删除

最后,再次序列化你的字典

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);
    }
公共字符串JsonMinusProperties(对象序列化)
{
//将此替换为获取不需要的属性的首选方法
var LinqMemberNames=toSerialize.GetType().GetProperties()。其中(y=>
y、 GetCustomAttributes(true).Any(x=>
x、 GetType().Namespace==“System.Data.Linq.Mapping”
)
).选择(x=>x.Name);
JavaScriptSerializer js=新的JavaScriptSerializer();
字符串json=js.Serialize(toSerialize);
var tempobj=js.DeserializeObject(json)作为字典;
foreach(LinqMemberNames中的字符串linqMember)
{
临时删除(linqMember);
}
返回js.Serialize(tempobj);
}

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

您可以看到DataMember属性的问题是,它与ScriptIgnore属性的问题相同。第二,我不想对这些东西做明确的DTO,因为除了额外的EF东西外,它们对运输非常好,而且解耦对我来说不是一个真正的问题。