17

To aid in debugging some code I'm working on, I started to write a method to recursively print out the names and values of an object's properties. However, most of the objects contain nested types and I'd like to print their names and values too, but only on the types I have defined.

Here's an outline of what I have so far:

public void PrintProperties(object obj)
{
    if (obj == null)
        return;

    Propertyinfo[] properties = obj.GetType().GetProperties();

    foreach (PropertyInfo property in properties)
    {
        if ([property is a type I have defined])
        {
            PrintProperties([instance of property's type]);
        }
        else
        {
            Console.WriteLine("{0}: {1}", property.Name, property.GetValue(obj, null));
        }
    }

The parts between the braces are where I'm unsure.

Any help will be greatly appreciated.

aligray
  • 2,812
  • 4
  • 26
  • 35
  • 1
    Possible duplicate of [C#: Printing all properties of an object](http://stackoverflow.com/questions/852181/c-printing-all-properties-of-an-object) – Michael Freidgeim Feb 23 '16 at 05:23

4 Answers4

28

The code below has an attempt at that. For "type I have defined" I chose to look at the types in the same assembly as the ones the type whose properties are being printed, but you'll need to update the logic if your types are defined in multiple assemblies.

public void PrintProperties(object obj)
{
    PrintProperties(obj, 0);
}
public void PrintProperties(object obj, int indent)
{
    if (obj == null) return;
    string indentString = new string(' ', indent);
    Type objType = obj.GetType();
    PropertyInfo[] properties = objType.GetProperties();
    foreach (PropertyInfo property in properties)
    {
        object propValue = property.GetValue(obj, null);
        if (property.PropertyType.Assembly == objType.Assembly && !property.PropertyType.IsEnum)
        {
            Console.WriteLine("{0}{1}:", indentString, property.Name);
            PrintProperties(propValue, indent + 2);
        }
        else
        {
            Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
        }
    }
}
carlosfigueira
  • 85,035
  • 14
  • 131
  • 171
  • 4
    This code doesn't detect _cycles_. If a cycle is present, it will end up throwing a `StackOverflowException`. – Jordão Jun 01 '11 at 17:19
  • True, some sort of "already visited" list would need to be maintained if cycles were possible in the domain of the problem. Thanks for pointing it out. – carlosfigueira Jun 01 '11 at 17:21
  • minute correction - last param in last Console.WriteLine should be {2} not {1} – zam6ak Jun 10 '11 at 21:13
  • Can you please explain what does this line: "if (property.PropertyType.Assembly == objType.Assembly)" do? – HoKy22 Dec 12 '13 at 22:10
  • 1
    It limits the recursion to only items in the same assembly of the type. Otherwise it would go on printing internal properties of classes such as string, Uri, DateTime, and so on. – carlosfigueira Dec 12 '13 at 23:07
  • In if (property.PropertyType.Assembly == objType.Assembly) you should check that the property is not enum. – Alex P. Jul 25 '14 at 07:11
12

Is there any particular reason why you want to use reflection? Instead you can use JavaScriptSerializer like this:

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
string json = serializer.Serialize(obj);
Console.WriteLine(json);

It will recursively include all properties in string, and throw exception in case if circular reference will appear.

Leonid Vasilev
  • 11,910
  • 4
  • 36
  • 50
  • this worked great for me, and working on a website, rather then `Console.WriteLine()` I used `div.InnerHtml = "";` and the output into Chrome's Console will even print pretty!!! (just for testing purposes of course) – Chad Nov 08 '17 at 19:23
4

Leverage from Leonid's answer, the below code is what I used to create a readable Json dump of any object. It ignores null field and add indentation for better view (especially good for SOAP objects).

public static string SerializeToLogJson(this object obj)
        {
            try
            {
                var json = JsonConvert.SerializeObject(obj,
                    Newtonsoft.Json.Formatting.None, 
                    new JsonSerializerSettings { 
                        NullValueHandling = NullValueHandling.Ignore,
                        Formatting = Formatting.Indented
                    });
                return json;
            }
            catch (Exception e)
            {
                log.ErrorFormat(e.Message, e);
                return "Cannot serialize: " + e.Message;
            }
        }
Community
  • 1
  • 1
Hoàng Long
  • 10,746
  • 20
  • 75
  • 124
4

Newtonsoft library provides very simple functions to serialize any object to JSON. This is a much simpler solution.

Newtonsoft.Json.JsonConvert.SerializeObject(objToSerialize);

for example:

dynamic obj = new { x = 1, y = 2, z = "abc" };
string json = JsonConvert.SerializeObject(obj);
//'json' string value: {"x":1,"y":2,"z":"abc"}
James Wierzba
  • 16,176
  • 14
  • 79
  • 120