在不同的场景中为给定的类生成不同的序列化JSON

时间:2015-06-17 10:12:28

标签: c# json serialization asp.net-mvc-5 json.net

更新1:由于我不会进入的原因,我想避免除了要在我的实体对象中保留的属性以外的任何内容。这意味着没有额外的属性或方法...

我有一个名为Entity1的实体(例如)有10个公共属性。在 在我的代码中的一个地方我想输出序列化的JSON(例如)3 那些领域,在第二个地方我需要输出7个字段和一个 第三名我可能需要输出(比方说)所有10个字段。我该怎么办 这是使用Newtonsoft的JSON库吗?

我无法使用[JsonIgnore][DataMember],因为这将适用于所有人 案件,所以我不能创建"自定义视图"数据(我自己的 术语: - )。

我尝试使用界面实现此目的:

public interface Entity1View1
{
    string Property1;
    string Property2;
    string Property5;
}

Entity1实施Entity1View1我通过了。{ {J}序列化程序IList<Entity1View1>(对象是 实际上只是Entity1个对象)。没有工作:串行器输出 Entity1的所有10个公共属性。

我能想到的另一种方式是实施 Entity1Wrapper1Entity1Wrapper2等各类的类型 对象将依次保存Entity1的相应实例 仅公开与属性对应的公共属性 我想在&#34; View1&#34;,&#34; View2&#34;然后我传递这些清单 对序列化程序的包装器对象(应该可以工作,还没有尝试过)。

有更好的方法吗?

如果重要,请点击此处:

  • .Net 4.5
  • MVC 5

3 个答案:

答案 0 :(得分:1)

不知道那是最好的方式......但那是一个。

一个好处是它可以用于json序列化或xml序列化(例如你可能根本不介意)。

您可以使用ShouldSerialize<yourpropertyName>来管理序列化的内容。 <yourpropertyName>必须与您要管理的媒体资源的名称完全匹配。

例如

public class Entity {
   //assuming you want the default behavior to be "serialize all properties"
   public Entity() {
       ShouldSerializeProperty1 = true;
       ShouldSerializeProperty2 = true;
       ShouldSerializeProperty3 = true;
   }
   public string Property1 {get;set;}
   public bool ShouldSerializeProperty1 {get;set;}

   public string Property2 {get;set;}
   public bool ShouldSerializeProperty2 {get;set;}

   public int Property3 {get;set;}
   public bool ShouldSerializeProperty3 {get;set;}
}

然后你可以在所有序列化之前(当然,这可能/应该是扩展方法)。

var list = myListOfEntity;

//serialization1
foreach (var element in list) {
   element.ShouldSerializeProperty3 = false;
}

//or serialization2
foreach (var element in list) {
   element.ShouldSerializeProperty2 = false;
   element.ShouldSerializeProperty3 = false;
}

答案 1 :(得分:1)

我只是想确保这是处理的最后一步。

您可以根据情况创建要序列化的匿名对象:

$db->query('SELECT * FROM table');
$db->exec('SELECT * FROM table');

您可以创建jsonSource1(或2,3,4等)作为匿名对象,捕获您需要的内容然后序列化它们。序列化程序不会关心它们是匿名的。

答案 2 :(得分:0)

更新1:

  

To conditionally serialize a property, add a method that returns boolean with the same name as the property and then prefix the method name with ShouldSerialize.

这意味着Raphaël Althaus建议的解决方案不起作用,因为它依赖于属性,而序列化程序的文档提到它必须是一种方法。我已经确认只返回bool的方法按预期工作。

原件:

我最终选择了Wrapper类和Raphaël Althaus建议的方法(带有修改):使用Wrappers可能需要一些复杂程度,并在简单性时使用Raphaël的建议。

以下是我使用包装器(故意省略null检查)的方法:

public class Entity1View1
{
    protected Entity1 wrapped;

    public Entity1View1(Entity1 entity)
    {
        wrapped = entity;
    }

    public String Property1
    {
        get { return wrapped.Property1; }
    }

    public String Property2
    {
        get { return wrapped.Property2; }
    }

    public String Property3
    {
        get { return wrapped.Property3.ToUpper(); }
    }
}

这允许我在返回值时修改属性(与上面的Property3一样),并让我利用继承来创建新的序列化方法。例如,我可以展平结构/层次结构:

public class Entity1View2 : Entity1View1
{
    pulic Entity1View2(Entity1 entity) : base(entity) { }

    public long? SubEntityID
    {
        get { return wrapped.SubEntity.ID; }
    }
}

对于不需要这种复杂性/转换的简单情况,我可以简单地使用ShouldSerialize*方法。

相同的实体类,不同的序列化输出。