Dumping a java object's properties

Viewed 78382

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.

10 Answers

You could try XStream.

XStream xstream = new XStream(new Sun14ReflectionProvider(
  new 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 ;)

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 static 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);
Related