Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serialize or deserialize a JSON Object to a certain depth in C#?

I only want the first depth level of an object (I do not want any children). I am willing to use any library available. Most libraries will merely throw an exception when the recursion depth is reached, instead of just ignoring. If this isn't possible, is there a way to ignore serialization of certain members given a certain datatype?

Edit: Let's say I have an object like so:

class MyObject {     String name = "Dan";     int age = 88;     List<Children> myChildren = ...(lots of children with lots of grandchildren); } 

I want to remove any children (complex types even) to return an object like this:

class MyObject {     String name = "Dan";     int age = 88;     List<Children> myChildren = null; } 
like image 795
John Russell Avatar asked May 04 '12 17:05

John Russell


People also ask

How do you serialize a JSON object?

NET objects as JSON (serialize) To write JSON to a string or to a file, call the JsonSerializer. Serialize method. The JSON output is minified (whitespace, indentation, and new-line characters are removed) by default.

What is serialize and deserialize in JSON?

JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).

What is JSON serialization in C#?

Serialization is the process of converting . NET objects such as strings into a JSON format and deserialization is the process of converting JSON data into . NET objects. In this article and code examples, first we will learn how to serialize JSON in C# and then we will learn how to deserialize JSON in C#.


1 Answers

This is possible in Json.NET using some coordination between the JsonWriter and the serializer's ContractResolver.

A custom JsonWriter increments a counter when an object is started and then decrements it again when it ends.

public class CustomJsonTextWriter : JsonTextWriter {     public CustomJsonTextWriter(TextWriter textWriter) : base(textWriter) {}      public int CurrentDepth { get; private set; }      public override void WriteStartObject()     {         CurrentDepth++;         base.WriteStartObject();     }      public override void WriteEndObject()     {         CurrentDepth--;         base.WriteEndObject();     } } 

A custom ContractResolver applies a special ShouldSerialize predicate on all properties that will be used to verify the current depth.

public class CustomContractResolver : DefaultContractResolver {     private readonly Func<bool> _includeProperty;      public CustomContractResolver(Func<bool> includeProperty)     {         _includeProperty = includeProperty;     }      protected override JsonProperty CreateProperty(         MemberInfo member, MemberSerialization memberSerialization)     {         var property = base.CreateProperty(member, memberSerialization);         var shouldSerialize = property.ShouldSerialize;         property.ShouldSerialize = obj => _includeProperty() &&                                           (shouldSerialize == null ||                                            shouldSerialize(obj));         return property;     } } 

The following method shows how these two custom classes work together.

public static string SerializeObject(object obj, int maxDepth) {     using (var strWriter = new StringWriter())     {         using (var jsonWriter = new CustomJsonTextWriter(strWriter))         {             Func<bool> include = () => jsonWriter.CurrentDepth <= maxDepth;             var resolver = new CustomContractResolver(include);             var serializer = new JsonSerializer {ContractResolver = resolver};             serializer.Serialize(jsonWriter, obj);         }         return strWriter.ToString();     } } 

The following test code demonstrates limiting the maximum depth to 1 and 2 levels respectively.

var obj = new Node {     Name = "one",     Child = new Node {         Name = "two",         Child = new Node {             Name = "three"         }     } }; var txt1 = SerializeObject(obj, 1); var txt2 = SerializeObject(obj, 2);  public class Node {     public string Name { get; set; }     public Node Child { get; set; } } 
like image 79
Nathan Baulch Avatar answered Sep 21 '22 09:09

Nathan Baulch