Monday, April 11, 2011

Dumping a java object's properties

Is there a library that will recursively dump/print an objects properties? I'm looking for something similar to the console.dir() function in Firebug.

I'm aware of the commons-lang ReflectionToStringBuilder but it does not recurse into an object. I.e., if I run the following:

public class ToString {

    public static void main(String [] args) {
        System.out.println(ReflectionToStringBuilder.toString(new Outer(), ToStringStyle.MULTI_LINE_STYLE));
    }

    private static class Outer {
        private int intValue = 5;
        private Inner innerValue = new Inner();
    }

    private static class Inner {
        private String stringValue = "foo";
    }
}

I receive:

ToString$Outer@1b67f74[ intValue=5
innerValue=ToString$Inner@530daa ]

I realize that in my example, I could have overriden the toString() method for Inner but in the real world, I'm dealing with external objects that I can't modify.

From stackoverflow
  • You could try XStream.

    XStream xstream = new XStream(new Sun14ReflectionProvider(
          FieldDictionary(new ImmutableFieldKeySorter())),
          new DomDriver("utf-8"));
    System.out.println(xstream.toXML(new Outer()));

    prints out:

    <foo.ToString_-Outer>
      <intValue>5</intValue>
      <innerValue>
        <stringValue>foo</stringValue>
      </innerValue>
    </foo.ToString_-Outer>

    You could also output in JSON

    And be careful of circular references ;)

    Kevin : Nice. I feel silly now because I use XStream a lot and I didn't even think of it.
    extraneon : Does that work with enum values? I believe (default) XML serialization using XMLEncoder.writeObject and hibernate have some problems with serializing enum values/types.
    cherouvim : @extraneon: sorry, I don't have much experience with Java 1.5 (enums etc)
  • Maybe you could use an XML binding framework like XStream, Digester or JAXB for that.

  • Scroll down for an example of dumping an object using reflection. http://stackoverflow.com/questions/37628/what-is-reflection-and-why-is-it-useful


    Or go directly to the answer.

  • You can use ReflectionToStringBuilder with a custom ToStringStyle, for example:

    class MyStyle extends ToStringStyle {
    private final static ToStringStyle instance = new MyStyle();
    
    public MyStyle() {
     setArrayContentDetail(true);
     setUseShortClassName(true);
     setUseClassName(false);
     setUseIdentityHashCode(false);
     setFieldSeparator(", " + SystemUtils.LINE_SEPARATOR + "  ");
    }
    
    public ToStringStyle getInstance() {
     return instance;
    };
    
    @Override
    public void appendDetail(StringBuffer buffer, String fieldName, Object value) {
     if (!value.getClass().getName().startsWith("java")) {
      buffer.append(ReflectionToStringBuilder.toString(value, instance));
     } else {
      super.appendDetail(buffer, fieldName, value);
     }
    }
    
    @Override
    public void appendDetail(StringBuffer buffer, String fieldName, Collection value) {
     appendDetail(buffer, fieldName, value.toArray());
    }
    

    }

    And then you invoke it like:

    ReflectionToStringBuilder.toString(value, MyStyle.getInstance());
    

    Beware of circular references though!


    You can also use json-lib (http://json-lib.sourceforge.net) and just do:

    JSONObject.fromObject(value);
    
  • JSONObject.fromObject(value)
    

    Does not work for Map objects with other keys than String. Maybe JsonConfig can handle this.

0 comments:

Post a Comment