【问题标题】:How to ignore properties when serializing to json that does not involve attributes序列化为不涉及属性的json时如何忽略属性
【发布时间】:2014-02-13 23:33:50
【问题描述】:

我正在使用实体框架来生成我的模型。我想通过 JSON 传达其中一些模型。问题是我不希望 EF 附加到模型上的东西被序列化(EntityKey、EntityState 和所有 EntityCollection 属性)

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

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

【问题讨论】:

    标签: c# json entity-framework-4


    【解决方案1】:

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

    我见过的大多数解决方案都希望包含属性(由于自动代码生成而无法实现)或滚动自定义转换器(矫枉过正,特别是如果您想捕获嵌套对象等)。

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

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

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

    终于再次序列化你的字典。

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 您看到 DataMember 属性的问题在于它与 ScriptIgnore 属性的问题相同。其次,我不想为这些东西制定明确的 DTO,因为除了额外的 EF 东西之外,它们非常适合传输,而解耦对我来说并不是真正关心的问题。
      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-07
        • 1970-01-01
        • 1970-01-01
        • 2019-08-02
        • 1970-01-01
        • 2014-07-31
        相关资源
        最近更新 更多