I have huge object, I have its class of course, I'm extracting some values from it, but since it is really big I don't know in which list or where the value I'm looking for is.
Is there a way to create some kind of object breakdown routing and search every part for the value I'm expecting, and it is hidden somewhere in the object, I just can't find it in eclipse its too nested.
I thought of using reflection to go trough all fields of object class and search for the value inside of each field(fields inside lists(list of lists etc)). Any other ideas?
Unfortunately none of these answers help me, I'm starting a bounty
I assume you just want to find a specific value and to trace its source. And all this, you want to do at debug time. I would suggest two options.
Option1 Use JSON - Serialize the object to json string and do a manual text search on the result. You would neeed json.jar (or any other parser) for this.
try {
System.out.println(new JSONObject(new YourHugeObject()).toString(5));
} catch (JSONException e) {
log(e);
}
Which will produce something like this. (I have simulated this by creating an object with some nested fields,lists,maps)
{
"ct": {
"a": 1,
"b": "sdf",
"f": 12,
"nested": {
"key1": {
"kk": "kk",
"ssdf": 123
},
"onemorekey": {
"kk": "kk",
"ssdf": 123
}
}
},
"doubleProp": 12.2,
"lngprop": 1232323,
"strProp": "123",
"stringlist": [
"String1",
"String2",
"String3"
]
}
Option2 Convert/Serialize the object to XML. Use XStream for this,which will be the easiest of all available parsers. With just two lines of code,
XStream stream = new XStream();
System.out.println(stream.toXML(new YourHugeObject()));
Which will produce,
<com.kmg.jsontools.test.JSTest>
<stringlist>
<string>String1</string>
<string>String2</string>
<string>String3</string>
</stringlist>
<strProp>123</strProp>
<doubleProp>12.2</doubleProp>
<lngprop>1232323</lngprop>
<ct>
<a>1</a>
<b>sdf</b>
<f>12.0</f>
<nested>
<entry>
<string>key1</string>
<com.kmg.jsontools.test.Type1>
<kk>kk</kk>
<ssdf>123</ssdf>
</com.kmg.jsontools.test.Type1>
</entry>
<entry>
<string>onemorekey</string>
<com.kmg.jsontools.test.Type1>
<kk>kk</kk>
<ssdf>123</ssdf>
</com.kmg.jsontools.test.Type1>
</entry>
</nested>
</ct>
</com.kmg.jsontools.test.JSTest>
Either of the above approaches,you can either print the result to the console or to a file and inspect it manually. Alternatively you can also use reflection,in which case you would have to write a lot of code and significant amount of time in testing it as well.
How about using the ToStringBuilder from Jakarta-Commons org.apache.commons.lang.builder package
.
System.out.println ( ToStringBuilder.reflectionToString( YOUR_OBJECT ) );
Create some static method, assuming:
Map<String, Object> DebugHelper.breakDown(Object bean)
And implement it (for example) as datamining. Usage of org.apache.pivot.beans.BeanAdapter - for example can help you to treat the bean as plain Map, or (as you have written - you need mine in depth) use recursion to group all properties into single large Map
Another useful signature:
Map<String, Object> DebugHelper.breakDown(Object bean, String lookFor)
where second parameter used to find substring of value's from from Map of first method.
Why is this helpful? Because you can using eclipse's inspector to calculate the result of this method in any time of debugging
If the class is Serializable, I often use XStream to dump an object to xml.
If not, here's some code to maybe get you started on the reflection mode. It's not as recursive as you need but could be modified pretty easily.
public static void debugPrint(Object o1)
{
if(o1 == null)
{
System.out.println(o1);
return;
}
Class c = o1.getClass();
do
{
printFields(c, o1);
c = c.getSuperclass();
}
while(c != null);
}
private static void printFields(Class c, Object o1)
{
Field[] fields = c.getDeclaredFields();
for(Field field : fields)
{
printField(field, o1);
}
}
private static void printField(Field field, Object o1)
{
try
{
if(Modifier.isFinal(field.getModifiers())) return; //Skip this guy, he's trouble!
field.setAccessible(true);
Object val = field.get(o1);
System.out.println(field.getName() + ":" + toString(val));
}
catch(IllegalAccessException ex)
{
System.out.println("Could not access field" + field.getName());
ex.printStackTrace();
}
}
private static String toString(Object o)
{
if(o instanceof Object[])
return Arrays.toString((Object[])o);
else
return String.valueOf(o);
}
I think you need to use reflection to get the data. Here is some code that should get you started:
static String search(Object o, final String search) {
try {
inspect(new HashSet<Object>(), o, new StringWriter() {
public void write(String s) {
System.out.println(s);
if (s.indexOf(search) >= 0) {
throw new RuntimeException(s) {
public Throwable fillInStackTrace() { return null; } };
}
}
});
return "not found";
} catch (Exception e) {
return e.getMessage();
}
}
private static void inspect(HashSet<Object> ignore, Object o, Writer w)
throws Exception {
if (o == null) {
return;
}
for (Class<?> c = o.getClass(); c != null ; c = c.getSuperclass()) {
if (c.isArray()) {
int len = Array.getLength(o);
for (int i=0; i<len; i++) {
inspect(ignore, Array.get(o, i), w);
}
} else if (c.isPrimitive()) {
w.write(o.toString());
} else {
for (Field f : c.getDeclaredFields()) {
if (!Modifier.isStatic(f.getModifiers())) {
f.setAccessible(true);
if (f.getType().isPrimitive()) {
w.write(f.getName() + ": " + f.get(o));
} else {
if (!ignore.contains(o)) {
ignore.add(o);
w.write(f.getName());
inspect(ignore, f.get(o), w);
}
}
}
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With