Saturday, September 18, 2010

TEAM.Commons: Formatting objects for human reading

This is the 3rd of several posts about TEAM.Common, a set of functionality I use in every project and that I'd like to share. The index is here:

Converting an arbitrary object into a human-readable string is something I need all the time, specially for logging.

TEAM.Commons has the PrettyFormat() extension method for the object class that performs this task. For an instance of a class like this:

public class CyclicClass
    public int IntProperty { get; set; }
    public SimpleClass SimpleProperty { get; set; }
    public CyclicClass CyclicProperty { get; set; }

The output of .PrettyFormat() would be:
CyclicClass {
SimpleProperty='SimpleClass {
 StringProperty='My string',
 DateProperty='3/2/2010 12:00:00 AM',
CyclicProperty='CyclicClass {
 SimpleProperty='SimpleClass {
  -- EXCLUDED (Too deep) --
  CyclicProperty='CyclicClass {
   -- EXCLUDED (Too deep) --

As you can see, by default it will go down only 1 level . Properties beyond that level will be rendered as "-- EXCLUDED (Too deep) --". There is an overload to specify an arbitrary deepness: .PrettyFormat(10).

The PrettyFormat method handles a lot of special cases: enum, IEnumerable, DateTimes, string, int, etc, providing an appropiate format for these types. You don't want to see an string as:
String {

but rather as:
The value of my string

Thanks to the "magic" of extension methods, you can even call it on null references, saving a lot of "if" instructions:

object o = null;

The output of the former code is: <NULL>

Remember, you can get all this code for free at bitbucket:

Check it out to get ideas, or simply use it as it is. It's working out for me and my team.


Román Fresneda Quiroga said...

Hi Rodo!

This one looks like json to me. Any thoughts on just reusing one of the json libraries out there?

Rodolfo Grave said...

Hi Roman.
The format is Json-inspired, but the intent is different.

For human-readability we need in-lining, new lines, control the deepness, formatted dates and numbers, custom outputs for enums, etc.

Using an existing Json serializer wouldn't have allowed me to control all this.