Parsing Javascript in Java, Javascript Objects - java

I am trying to parse a Javascript file using ScriptEngine in Java. I am not interested in executing scripts, just parsing it to get some values.
The script files are comprised of a series of arrays with this structure:
var array= new Array();
array[0]=new Array();
array[0]['point']=new Point2D(2.454,-8.33);
array[0]['name']='Object 1';
array[1]=new Array();
array[1]['point']=new Point2D(42.84, 3.53);
array[1]['name']='Object 2';
...
with Point2D defined as:
function Point2D(x,y) {
this.x = x;
this.y = y;
}
So far I've parsed the script with this code:
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine se = mgr.getEngineByName("JavaScript");
try {
se.eval(file);
NativeArray array = (NativeArray)se.get("array");
for(int i = 0; i < array.getLength(); i++){
if(array.get(i)!=null){
NativeArray elementArray = (NativeArray)array.get(i);
System.out.println("Object: " + elementArray);
System.out.println("name: " + elementArray.get("name", elementArray));
System.out.println("point: " + elementArray.get("point", elementArray));
}
}
}
catch (ScriptException e) {
....
}
Which gives me the name properly, but I get an instance of Object class for the Point2D item. Since it was originally a javascript object, how can I parse it to obtain x and y values?

You could do it like this:
NativeObject point;
NativeArray elementArray;
for(int i = 0; i < array.getLength(); i++){
if(array.get(i)!=null){
elementArray = (NativeArray)array.get(i);
System.out.println("name: " + elementArray.get("name", elementArray));
point = (NativeObject) arrayFirstElement.get("point", arrayFirstElement);
//System.out.println("point.x: " + NativeObject.getProperty(point, "x"));
//System.out.println("point.y: " + NativeObject.getProperty(point, "y"));
System.out.println("object point has: ");
for ( Object propertyId : NativeObject.getPropertyIds(point)){
System.out.println("property "+ propertyId + " has value " + NativeObject.getProperty(point, propertyId.toString()));
}
}
}
But take a look at these tutorials: 1 ,2, you might get some fresh ideas :)

Well, thanks to #Pointy I figured out the solution, I injected this code inside the if statement:
se.eval("var x = array[" + i + "]['point'].x; var y = array[" + i + "]['point'].y;", se.getBindings(ScriptContext.ENGINE_SCOPE));

Related

Parse JSON multiple objects

I am trying to parse the below json but unable to do that as stack over flow error comes in.
Here is the JSON -
[{
"Class": "1",
"school": "test",
"description": "test",
"student": [
"Student1",
"Student2"
],
"qualify": true,
"annualFee": 3.00
}]
Here is the code which is failing currently.
String res = cspResponse.prettyPrint();
org.json.JSONObject obj = new org.json.JSONObject(res);
org.json.JSONArray arr = obj.getJSONArray(arrayName);
String dataStatus=null;
for (int i = 0; i < arr.length(); i++) {
dataStatus = arr.getJSONObject(i).getString(key);
System.out.println("dataStatus is \t" + dataStatus);
}
Usecases are:
To get the value key "class"
Get the value from Student
Get the value from school
I appreciate your help.
update-1
Code more info on stack trace updated with below details.
cls = 1
error- org.json.JSONException: JSONObject["student "] not a string.
Stack trace-
public String getString(String key) throws JSONException {
Object object = this.get(key);
if (object instanceof String) {
return (String) object;
}
throw new JSONException("JSONObject[" + quote(key) + "] not a string.");
}
When I ran the code with the below answers, here its failing for student is not a string.
The answers I used from first two comments and both have the same error. I appropriate your help.
Your json fragment is invalid - the last comma breaks the parsing. But the rest of the code is quite workable.
String res = "[\n" +
" {\n" +
" \"Class\": \"1\",\n" +
" \"school\": \"test\",\n" +
" \"description\": \"test\",\n" +
" \"student\": [\n" +
" \"Student1\",\n" +
" \"Student2\"\n" +
" ],\n" +
" \"qualify\": true,\n" +
" \"annualFee\": 3.00\n" +
" }\n" +
"]";
JSONArray arr = new JSONArray(res);
for (int i = 0; i < arr.length(); i++) {
JSONObject block = arr.getJSONObject(i);
Integer cls = block.getInt("Class");
System.out.println("cls = " + cls);
Object school = block.getString("school");
System.out.println("school = " + school);
JSONArray students = block.getJSONArray("student");
System.out.println("student[0] = " + students.get(0));
System.out.println("student[1] = " + students.get(1));
}
should output
cls = 1
school = test
student[0] = Student1
student[1] = Student2
Your JSON reponse root is array but you consider your JSON response as JSON object
Changing your parsing json code as below
String res=cspResponse.prettyPrint();
org.json.JSONArray arr = new org.json.JSONArray(res);
String dataStatus=null;
for (int i = 0; i < arr.length(); i++) {
org.json.JSONObject obj=arr.getJSONObject(i);
dataStatus = obj.getString(key);
System.out.println("dataStatus is \t" + dataStatus);
String schoolName = org.getString("school");
System.out.println("school => " + schoolName);
org.json.JSONArray students = obj.getJSONArray("student");
System.out.println("student[0] = " + students.get(0));
System.out.println("student[1] = " + students.get(1));
}
You can use simple JSONObject class and Simple JSONParser for parsing the JSON.
1. Parse the JSON.
org.json.simple.JSONParser parser = new org.json.simple.JSONParser();
org.json.simple.JSONObject parsedJSON = parser.parse(inputJSON);
2. To get class:
String class = parsedJSON.get("Class");
3. To get Students:
org.json.simple.JSONArray studentArray = parsedJSON.get("student");
4. To Get School:
String school = parsedJSON.get("school");
After the above steps, you can run a for-loop to print the class and students.

Android JSONObject need print null

data from:
{"i":"One","o":"two","u":"","a":"four"}
code:
JSONObject data;
for (int i = 0; i < list.length(); i++) {
data = list.optJSONObject(i);
mSearchList.add(data.optString("o") + " " +
data.optString("u")+ " " + data.optString("a"));
}
print:
i=one
o=two
u=
a=four
I need print:
i=one
o=two
u=null
a=four
how to do?Thank you read my question ,please help me
As Sotirios Delimanolis said, you can check if that is a empty string, return "null" text.
for (int i = 0; i < list.length(); i++) {
data = list.optJSONObject(i);
mSearchList.add(
data.optString("o").equals("") ? "null" : data.optString("o") + " " +
data.optString("u").equals("") ? "null" : data.optString("u") + " " +
data.optString("a").equals("") ? "null" : data.optString("a"));
}
Use this method
getValidString(JSONObject json,String key){
String value="";
try{
value=json.getString(key);
}catch(Exception e){
e.printStackTrace();
}
if(value.length==0){
value="null";
}
}

public static runtime incremental change - android

I have a simple class named A which has two private fields.
public class A {
private String a;
private String b;
} // A
When I get all declared fields from class instance, I get one extra field named $change of type com.android.tools.fd.runtime.IncrementalChange. Where is it coming from ? I am totally not getting this.
Field[] fields = cls.getDeclaredFields();
for (int i = 0, len = fields.length; i < len; i++) {
Field field = fields[i];
field.setAccessible(true);
Log.d("TAG", field.getName());
if (field.isAnnotationPresent(Primary.class)) {
query += getFromalName(field.getName()).toUpperCase() + " " + getSchemaType(field.getType().getSimpleName()) + " PRIMARY KEY, ";
continue;
}
if (field.isAnnotationPresent(NotNull.class)) {
query += getFromalName(field.getName()) + " " + getSchemaType(field.getType().getSimpleName()) + " NOT NULL, ";
continue;
}
query += getFromalName(field.getName()) + " " + getSchemaType(field.getType().getSimpleName()) + ", ";
} // end for
query = query.substring(0, query.lastIndexOf(","));
query += " )";
It was added to support instant run. Disabling instant run solved the problem. here
is the link to android issue tracker

How to generate a PNG image from a dot file format with Graphviz

I have a java class that implements a priority queue. Then I have a class test that generates a graph like this:
digraph G {
Milan (0.0) -> Turin (1.2)
Milan (0.0) -> Montreal (7.0)
Turin (1.2) -> Paris (5.8)
Turin (1.2) -> Tokyo (2.2)
}
This graph is saved in a file called "queue".
Now I wish that this graph was displayed in a PNG image using Graphviz.
So the last call of my test files (after you have created and filled the queue with priority) is:
queue.toString("queue");
All right. The toString method is the following:
public void toString(String fileDot){
try {
FileOutputStream file = new FileOutputStream(fileDot);
PrintStream Output = new PrintStream(file);
Output.print(this.printQueue());
Output.close();
File f = new File(fileDot);
String arg1 = f.getAbsolutePath();
String arg2 = arg1 + ".png";
String[] c = {"dot", "-Tpng", arg1, "-o", arg2};
Process p = Runtime.getRuntime().exec(c);
int err = p.waitFor();
}
catch(IOException e1) {
System.out.println(e1);
}
catch(InterruptedException e2) {
System.out.println(e2);
}
}
private String printQueue() throws IOException {
String g = new String("");
char c = '"';
g = g.concat("digraph G {\n");
if(isEmpty())
g = g.concat(" " + "Empty priority queue.");
else {
for(int i = 0; i < lastIndex; i++) {
if(heap[2 * i] != null) {
g = g.concat("" + heap[i].elem + " (" + heap[i].prior + ") " + " " + " -> " + " " + "" + heap[i * 2].elem + " (" + heap[i * 2].prior + ") \n" );
if(heap[2 * i + 1] != null)
g = g.concat("" + heap[i].elem + " (" + heap[i].prior + ") " + " " + " -> " + " " + "" + heap[i * 2 + 1].elem + " (" + heap[i * 2 + 1].prior + ") \n" );
}
} //end for
} //end else
g = g.concat("}");
return g;
}
Why is not generated image .png? Where am I wrong?
Of course I installed Graphviz.
Thanks
When I ran the .dot file above through dot at the command line, I got:
$ dot -Tpng queue.dot -oqueue.png
Warning: queue.dot:2: syntax error in line 2 near '('
Thus, the parenthesised numbers in the node names are not valid in dot syntax. If you remove them, I expect the .png file would be created successfully. If you need the parenthesised numbers in your output, I suggest looking up node labels in the GraphViz documentation.
I'd also note that toString() does not seem like a particularly clear name for a function that creates a .png file so changing the name of the function might be advisable.
Try using dot's -O option instead of -o. According to dot -? here's what it does:
Automatically generate an output filename based on the input filename with a .'format' appended. (Causes all -ofile options to be ignored.)
So you could change
String[] c = {"dot", "-Tpng", arg1, "-o", arg2};
to
String[] c = {"dot", "-Tpng", arg1, "-O"};

CR4E Crystal Reports save modified ChartObject

I am attempting to programatically modify a chart within a Crystal Report using Java. The java then feeds the report to the viewer. Removing an item works, modifying does not.
//Experiment : Can we programatically modify a chart?
ReportDefController rdc = reportClientDocument.getReportDefController();
ReportObjectController roc = rdc.getReportObjectController();
ReportObjects ros = roc.getReportObjectsByKind(ReportObjectKind.chart);
logger.debug("There are " + ros.size() + " chart items");
IChartObject ro = null;
IChartObject ro_original = null;
ISection iSection = null;
for (int i = 0; i <ros.size(); i++){
ro = (IChartObject)ros.get(i);
ro_original = (IChartObject)ros.get(i);
String rn = ro.getName();
ChartStyle cs = (ChartStyle) ro.getChartStyle();
cs.setEnableDataAxisAutoRange(false);
cs.setEnableShowLegend(false);
cs.setEnableDepthEffect(true);
cs.setIsVertical(true);
cs.setDataAxisMinValue(-2.0);
cs.setDataAxisMaxValue(100.0);
Double minVal = (Double)cs.getDataAxisMinValue();
Double maxVal = (Double)cs.getDataAxisMaxValue();
boolean d = cs.getEnableDepthEffect();
boolean l = cs.getEnableShowLegend();
boolean a = cs.getEnableDataAxisAutoRange();
boolean v = cs.getIsVertical();
ro.setChartStyle(cs);
int sectionCode = ro.getSectionCode();
iSection = rdc.getReportDefinition().getDetailArea().getSections().getSection(0);
try
{
//roc.modify((IChartObject)ros.get(i), ro);
rdc.modifyChartObject((IChartObject)ros.get(i), ro);
reportClientDocument.refreshReportDocument();
reportClientDocument.save();
} catch (ReportSDKException e){
writer.println("Couldn't modify graph");
e.printStackTrace();
}
logger.debug("Chart named "+rn + " With Min Val " + minVal + " and Max Val " + maxVal +" with depth " + d + " and legend " + l + " autorange " + a + " Vertical " + v);
}
I've tried the modify method of ReportObjectController and the modifychartobject method of ReportDefController, and have tried refreshReportDocument and save to attempt to get something to update, but nothing's happening. Logger is showing that the values are updating as you'd expect. Any ideas?
My mistake was in not cloning the object at...
ro = (IChartObject)ros.get(i)
...so it should read...
ro = (IChartObject)ros.get(i).clone(false)
..so that..
roc.modify((IChartObject)ros.get(i), ro)
.. will now work. Hope this helps someone else having similar fun and games.

Categories