1

I am working on a project in .NET 6 and I need to serialize objects to JSON (and deserialize from JSON as well) in a specific way. These are the "rules":

  1. If a property is a nested object, and it's null, skip it entirely
  2. If a nested object has only null or empty values, skip it entirely
  3. If a property is a string, and it is null or empty, skip it entirely
  4. If a property is an empty IEnumerable, skip it entirely

Additionally, I'd like to avoid coupling my model to any concrete JSON serializer, so I'm trying to avoid using attributes. Lastly, I am looking for a generic serialization method.

So if I had a class like this one:

public class MyOuterClass
{
    public string Name { get; set; }
    public string Email { get; set; }
    public MyInnerClass InnerOne { get; set; }
    public MyInnerClass InnerTwo { get; set; }
    public List<YetAnotherClass> ListProp { get; set; } = new List<YetAnotherClass>();
}

public class MyInnerClass
{
    public string NameInner { get; set; }
}

And instantiated it like this:

var value = new MyOuterClass
{
    Name = "My Name",
    Email = "",
    InnerOne = null,
    InnerTwo = new MyInnerClass { NameInner = "" }
};

Calling something like:

_mySerializer.Serialize<MyOuterClass>(value);

Should return:

{
    name: "My Name"
}

Is there any way to achieve this only with System.Text.Json.Serialization or Newtonsoft.JSON? I'd like to avoid writing completely custom code with reflection and recursion.

dzenesiz
  • 1,388
  • 4
  • 27
  • 58
  • .NET 5 and 6 are .NET *Core* 5 and 6. The name was changed for marketing reasons. The `.net` tag is used for .NET Framework. – Panagiotis Kanavos Jan 19 '22 at 13:19
  • @PanagiotisKanavos I edited a question as well... a force of habit. Thanks for pointing that out. – dzenesiz Jan 19 '22 at 13:26
  • Which version are you using? .NET 6 uses source generators, which means that reflection may not be an option, or require specific switches to disable source generators – Panagiotis Kanavos Jan 19 '22 at 13:28
  • It is .NET 6... – dzenesiz Jan 19 '22 at 14:17
  • 1
    System.Text.Json doesn't even support conditional serialization, see [Custom JSON serializer for optional property with System.Text.Json](https://stackoverflow.com/q/63418549/3744182), [ShouldSerialize method is not triggered in .NET Core 3](https://stackoverflow.com/q/59507818/3744182) and [C# .Net Core 3.1 System.Text.Json Ignore empty collection in serialization](https://stackoverflow.com/q/59720612/3744182). So the only way to achieve the conditional serialization you require is with *completely custom code with reflection and recursion*. – dbc Jan 19 '22 at 18:02
  • 1
    Most of what you want would be easier with Json.NET, but even there conditional serialization ***based on depth*** is problematic because Json.NET is a contract-based serializer. It makes a contract for each type, then serializes instances of the type based on the contract no matter where they are encountered in the serialization graph. To serialize differently based on depth requires fairly elaborate code, see [Json.NET serialize by depth and attribute](https://stackoverflow.com/q/36159424/3744182) or [Json.NET serialize by depth and attribute](https://stackoverflow.com/q/36159424/3744182). – dbc Jan 19 '22 at 18:09
  • As a workaround, in .NET 6 you might consider serializing to an intermediate `JsonNode`, pruning undesired values, then returning the serialized node. (With Json.NET the same effect could be achieved by serializing to `JToken`). Would that approach meet your needs? – dbc Jan 19 '22 at 18:10
  • 1
    @PanagiotisKanavos - source generators are optional with System.Text.Json in .NET 6. – dbc Jan 19 '22 at 18:13
  • @dbc I know very little about serialization, so I'll have to try and see. But I'll let you know if your comments are sufficient for an answer should you what to write an answer I can accept. Thanks! – dzenesiz Jan 19 '22 at 19:39
  • I actually went for a full reflection-based solution using `ExpandoObject` as an intermediary to save only allowed properties in. – dzenesiz Jan 24 '22 at 11:34

0 Answers0