1

There is tons of info about skipping Properties based on conditionals, but I would like to skip the entire object based on conditions within the object's class. I would like a solution that is contained within the object's class if at all possible. Keep in mind this is a collection of myObj that I am serializing.

public class myObj
{
    bool conditional;
    ShouldSerialize()
    {
        return conditional;
    }
}

Or

public class myObj
{
    [JsonCondition]
    public bool conditional{get;}
}

Or even

[JsonCondition(typeof(MyConditionChecker))]
public class myObj
{
    public bool conditional{get;}
}

class MyConditionChecker: JsonCondition
{
    public override bool CanConvert(object sourceObj)
    {
        return (sourceObj as myObj).conditional;
    }
}
Wobbles
  • 3,033
  • 1
  • 25
  • 51

2 Answers2

1

What I got from your comments you would be best served creating your own wrapper around Json that applies the filtering.

public interface IConditionalSerializer
{
    bool ShouldBeSerialized();
}

public static class FilteredSerializer
{
    public static string SerializeConditional<T>(IEnumerable<T> input)
        where T : IConiditionalSerializer
    {
        return JsonConvert.SerializeObject(input.Where(e => e.ShouldBeSerialized()));
    }
}

public class Demo : IConditionalSerializer
{
     public bool ShouldBeSerialized() => false;
}

You might also replace the interface with a reflection approach, but keep in mind the performance loss.

public interface IConiditionChecker
{
    bool ShouldBeSerialized(object instance);
}

public class ConditionAttribute : Attribute
{
    public Type ConditionChecker { get; set; }
}

public static class FilteredSerializer
{
    public static string SerializeConditional(IEnumerable<object> input)
    {
        var matches = (from entry in input
                       let att = entry.GetType().GetCustomAttribute<ConditionAttribute>()
                       let hasChecker = att != null && att.ConditionChecker != null
                       let checker = hasChecker ? (IConiditionChecker)Activator.CreateInstance(att.ConditionChecker) : null
                       where checker.ShouldBeSerialized(entry)
                       select entry);
        return JsonConvert.SerializeObject(matches);
    }
}

[Condition(ConditionChecker = typeof(SomeChecker))]
public class Demo
{
}

Edit: Based on your comment you could do this. Only must decide wether to use opt-in or opt-out in the where-statement. It must ether be casted != null && casted.ShouldBeSerialized or what it currently says.

public interface IShouldBeSerialized
{
    bool ShouldBeSerialized();
}

public static class FilteredSerializer
{
    public static string SerializeConditional(IEnumerable<object> input)
    {
        var matches = (from entry in input
                       let casted = entry as IShouldBeSerialized
                       where casted == null || casted.ShouldBeSerialized()
                       select entry);
        return JsonConvert.SerializeObject(matches);
    }
}

public class Demo : IShouldBeSerialized
{
    public bool ShouldBeSerialized()
    {
        return false;
    }
}
Toxantron
  • 2,218
  • 12
  • 23
  • The second approach is intriguing, I would probably simplify it by applying a interface `IShouldSerialize` directly to the class. Then just check object types and if it implements my interface check the property. That keeps it reuseable throughout my application which I like. – Wobbles Apr 08 '16 at 12:20
-1

If you're able to use the JSON.NET serializer, in terms of not serializing specific items within a collection, you could make the main collection non serializable, then add another filtered collection that does serialize.

public class Manager
{
   [JsonIgnore]
   public Employee[] Employees { get; set; }

   [JsonProperty("Employees")]
   public Employee[] SerializableEmployees
   {
       get { return Employees.Where(e => e.Name != "Bob").ToArray(); }
       set { Employees = value; }
   }
}

Alternatively, you could mark your class with the [JsonConverter] attribute and use a custom converter to check your condition. A similar approach that ignores a class entirely is detailed here.

Community
  • 1
  • 1
Reddog
  • 15,219
  • 3
  • 51
  • 63
  • This is about serializing properties which I say in my very first sentence that I am aware of. I am trying to skip the entire `myObj` in a collection of `myObj` that is not wrapped or contained in another object. – Wobbles Apr 08 '16 at 11:27
  • And why not use LinQ or write your own extension? – Toxantron Apr 08 '16 at 11:54
  • @Toxantron linq is what I am doing now, was hoping to find a class object side Json native feature that I could leverage to do this. Json has had everything else I could imagine, just a bit surprised to not see something I could leverage to do this built in. – Wobbles Apr 08 '16 at 12:15