Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert Neo4j JSON to Java Object

Tags:

java

neo4j

I've been playing with Neo4j 2.0 RC1 for a couple of weeks. I'm writing a Spring Security implementation using Neo4j as the database. When I load a user, the response I get from Neo4j looks like this:

{
    "columns" : [ "username", "password", "accountNonExpired","accountNonLocked", "credentialsNonExpired", "enabled" ],
    "data" : [ [ "admin", "admin", true, false, true, false ]
}

Originally the only fields returned where username and password (both strings) and I was able to do this:

class Result
{
    private List<String> columns = new ArrayList<String>();

    private List<ArrayList<String>> data = new ArrayList<ArrayList<String>>();

};

ClientRespose resp = webResource.path(path).type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).post(ClientResponse.class, body );
String s = response.getEntity(String.class);
Result r = new Gson().fromJson(s, Result.class);

Of course when I added the other fields (booleans) I needed to change Result to look like this:

class Result
{
    private List<String> columns = new ArrayList<String>();

    private List<ArrayList<Object>> data = new ArrayList<ArrayList<Object>>();

};

My code still worked, but when I tried to cast any of the data items to String or Boolean I got a 'failed to cast Object to...' exception. This is of course because there is no type information, so GSon is creating Object instances to put everything it.

So I'm guessing there must be a better way to process the JSON that comes back from Neo4j?

Can I somehow skip the JSON conversion stage and get the Jersey HTTP client to populate my User objects directly?

like image 333
Paul Grenyer Avatar asked Dec 24 '13 11:12

Paul Grenyer


1 Answers

The problem is that the data is not returned as map.

I usually do this:

  1. get the result as Map
  2. get the columns list
  3. get the data nested list
  4. using an for loop over data to get each row
  5. using a for loop over columns and it's index to access the data in the row

You can also add a factory method to your user Object that gets one of these results rows and constructs your User object.

e.g.

class User {
   public static User from(List<Object> row) {
      User u=new User((String)row.get(0),(String)row.get(1));
      u.setAccountNonExpired((Boolean)row.get(2));
      u.setAccountNonLocked((Boolean)row.get(3));
      u.setCredentialsNonExpired((Boolean)row.get(4));
      u.setEnabled((Boolean)row.get(5));
      return u;
   }
}

Something you can try with Neo4j 2.0 is to use the transactional endpoint and return the node object (which will return just the node-properties as a map), which you then can map directly with Gson or Jackson to an object (the row).

match (u:User {username:{username}})
return u

otherwise you can also use the literal map syntax in Neo4j 2.0

match (u:User {username:{username}})
return {username : u.username, password: u.password, ....} as user
like image 99
Michael Hunger Avatar answered Sep 25 '22 11:09

Michael Hunger