I have currently written a program that retrieves the JSON result of a Cypher query that I have made to a Neo4j database using the REST API. This project has was written in Android Studio, and the code for it is listed below:
public class MainActivity extends AppCompatActivity {
private TextView userText;
private Button clicker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userText = (TextView) findViewById(R.id.txtUsername);
clicker = (Button) findViewById(R.id.btnClick);
clicker.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//The REST API needs it's own thread for Neo4j connection. Read up on this documentation.
AsyncTask.execute(new Runnable() {
@Override
public void run() {
try {
//The URL will change based on what is needed for the documentations.
//Provides the address for the HTTP communication.
String neo4jURL = "http://ec2-35-176-79-15.eu-west-2.compute.amazonaws.com:7474/db/data/cypher";
//Helps to create the JSON object used by the query.
//QueryData neo4jqueryData = new QueryData();
//Creates the client used for the connection.
HttpClient neo4jClient = new DefaultHttpClient();
//Assigns the address to either the HttpGet or HttpPost request.
HttpPost neo4jRequest = new HttpPost(neo4jURL);
//Creates the JSON Attributes that will be used as part of the query.
String query = "MATCH (n:Student) WHERE n.Username=\'cs16thm\' RETURN n.StudentID";
JSONObject neo4jJSON = new JSONObject();
neo4jJSON.put("query",query);
//neo4jJSON.put("params","");
String check = neo4jJSON.toString();
Log.d("JSON",check);
StringEntity queryString = new StringEntity(check,"UTF-8");
//Ensures that the application type is JSON.
queryString.setContentType("application/json");
//Adds the Attribute data to the JSON query.
neo4jRequest.setEntity(queryString);
//Adds the Headers to the query.
//bmVvNGo6Z3JvdXAzNw== is the Base64 encoding of the username and password.
neo4jRequest.setHeader("Authorization","Basic bmVvNGo6Z3JvdXAzNw==");
//Shows the data types that would be accepted by the query result.
neo4jRequest.setHeader("Accept", "application/json; charset=UTF-8");
//Used to show the data type being sent to the server.
neo4jRequest.setHeader("Content-Type", "application/json");
//Performs the neo4j query.
HttpResponse queryResult = neo4jClient.execute(neo4jRequest);
//Checks the status code of the request.
int statusCode = queryResult.getStatusLine().getStatusCode();
if (statusCode == 200){
Log.d("CONNECT","Query Made " + Integer.toString(statusCode));
//Gets the results stream from the connection. Results is returned as a JSON which needs to be parsed.
InputStreamReader resultsReader = new InputStreamReader(queryResult.getEntity().getContent());
JsonReader JsonReader = new JsonReader(resultsReader);
//Begins processing of the JSON results.
JsonReader.beginObject();
//Checks all of the parameter keys returned by the document.
Log.d("PARSE","Begin JSON Parse");
while(JsonReader.hasNext()){
//Gathers the name of the current key.
String resultKey = JsonReader.nextName();
Log.d("RESULT","Entered Loop " + resultKey);
//Checks if it's the data we're looking for, and if it contains a value.
if(resultKey.equals("data") && JsonReader.peek() != JsonToken.NULL){
Log.d("RESULT","Entered IF Block");
//Begin array needs to go here.
JsonReader.beginArray();
//Gathers the String value that we require.
String result = JsonReader.nextString();
//Shows the result in the application.
Log.d("RESULT","Result=" + result);
//Prevents further loop execution now that our data is retrieved.
JsonReader.endArray();
break;
} else {
//Skips to the next value if the current one contains nothing of interest.
JsonReader.skipValue();
}
}
Log.d("PARSE","End JSON Parse");
JsonReader.endObject();
//JsonReader.endObject();
//Closes the JSON reader after task to prevent resource hogging.
JsonReader.close();
} else {
Log.d("ERROR", "Request not made " + Integer.toString(statusCode));
}
} catch (MalformedURLException e) {
e.printStackTrace();
Log.d("ERROR", "Bad URL");
} catch (IOException ioe) {
ioe.printStackTrace();
Log.d("ERROR", "Cannot Connect");
} catch (Exception par){
par.printStackTrace();
Log.d("ERROR", "Parse Fail");
}
}
});
}
});
}
}
The query is successful, producing an HTTP 200 code and code is running correctly untill the error message Expected a string but was BEGIN_ARRAY
and IllegalStateException
are thrown for the line String result = JsonReader.nextString();
. In order to try to address this error, I added the JsonReader.beginArray()
and JsonReader.endArray()
lines into the code before and after the exception throwing statement. However, the same error messages are still being produced for the same line of code. Based on Neo4j documentation at: (https://neo4j.com/docs/rest-docs/current/, Section 3.6), the JSON result I would be parsing should follow a similar format to this example:
{
"columns" : ["n.StudentID"],
"data" : [ ["1607174"] ]
}
Finally, the code currently uses the Apache Http Client and Google Simple JSON llibraries in case that is affecting anything. Any insights or solutions to this problem would be greatly apriciated and if you have any further questions, please feel free to ask. Also any other suggestions that would allow me to correctly parse this JSON result would also be welcomed.