Walk over a complex object graph in Java and get index to an attribute (similar to xpath)

2k views Asked by At

Problem Statement:

Imagine a nested object like below:

class Company{
...
List<Department> departments;
}

class Department{
...
List<Employee> employees;
}

class Employee{
String name;
...
}

A company has many departments, and each department has many employees.

Json body is unmarshalled by a library, to create the Java object Company as shown above.

Suppose I had an employee with name:"John", I am looking for an api, which when I pass in the hash of Employee object or the attribute name returns a Path to that attribute.

search(Object attributeName, Object attributeValue) i.e search("name", "John") should return company.departments[0].employees[5]

Is there a good open source library exposing similar api or what is the best method around to walk over a complex object graph

JSR 303 Hibernate Validator, which adds property path automatically to a ConstraintViolation doesn't expose the behavior on how it gets property path from complex object graphs via any object

Kindly advice if anyone has run through a similar need

2

There are 2 answers

1
Dele Taylor On

I haven't seen a library that does exactly this, but you can modify the code from my object iterator blog to do this.

https://blog.stackhunter.com/2014/07/09/convert-java-objects-to-string-with-the-iterator-pattern/

The iterator navigates an object graph to produce output like the following, but you can make it do anything -- including searching for a key-value pair.

com.stackhunter.example.employee.Department@129719f4
  deptId = 5775
  employeeList = java.util.ArrayList@7037717a
employeeList[0] = com.stackhunter.example.employee.Employee@17a323c0
  firstName = Bill
  id = 111
  lastName = Gates
employeeList[1] = com.stackhunter.example.employee.Employee@57801e5f
  firstName = Howard
  id = 222
  lastName = Schultz
employeeList[2] = com.stackhunter.example.employee.Manager@1c4a1bda
  budget = 75000.0
  firstName = Jeff
  id = 333
  lastName = Bezos
  name = Sales
[I@39df3255
  object[0] = 111
  object[1] = 222
  object[2] = 333

Happy coding!

0
Hubbitus On

You can use SOJO (Simplified Old Java Objects).

According to theirs documentation i think PathRecordWalkerInterceptor is what you are search:

Car car = new Car("Ferrari");
ObjectGraphWalker walker = new ObjectGraphWalker();
PathRecordWalkerInterceptor interceptor = new PathRecordWalkerInterceptor();
walker.addInterceptor(interceptor);

walker.walk(car);
Map visitedPathes = interceptor.getAllRecordedPathes();