Magic Properties from PHP in Java - java

in PHP I have a Model class, that loads data from the database. Since many other classes use this Model, it's easy for me to load variables like this.
public function loadModel( $id ) {
$result = $this->queryData( self::RETURN_MODE_ASSOC, array(), array('id' => $id ));
if (count($result) > 0 ) {
$this->loadRow( $result[0] );
return true;
}
return false;
}
public function loadRow( $row ) {
foreach ($row as $key=>$val) {
$this->$key = $val;
}
}
Now, for each Class that uses the model. I can simply access these variables. How is that possible in Java? I have a class
User and a Model named Model.
I mean, I can't simply use this.key like this
JSONObject jsonObj = new JSONObject(result);
Iterator iter = jsonObj.keys();
while(iter.hasNext()){
this.key = (String)iter.next();
}
Is it possible in Java to do this/

Related

JSONObject parse dictionary objects

JSON values that I get from server:
{
"Status":0,
"Message":"",
"Result":{"0B":"S.C. Blue Air","0Y":"FlyYeti","1X":"Branson Air"}
}
Getting the result as 'response' after connection and I am able to show my JSON string results on the screen.
JSONObject json = new JSONObject(response);
String status = json.getString("Status");
String message = json.getString("Message");
String result = json.getString("Result");
responseView.setText("Status" + status+ "Message" + message" + Result" + result);
I am okay the results of "Status" and "Message" but not with "Result" because want to separate "Result" objects as and able use each of them as objects.
For example:
When I type OB in my app, I will get the result S.C. Blue Air
Instead of :
String result = json.getString("Result");
use
if(json.get("Result") instanceof JSONObject){
JSONObject object = (JSONObject) json.get("Result");
//do what you want with JSONObject
String ob = object.get("0B");
}
If you want to store it some way you can put it to Map or create object if always it is same data
You can use some libraries such as Gson (Google) or Moshi (Square)
Those libraries allows you to declare your model as a plain java class (commonly called POJOS) annotated in some way that this libraries bind your properties in the JSON to your java properties.
In your case:
JSON:
{
"Status":0,
"Message":"",
"Result":{"0B":"S.C. Blue Air","0Y":"FlyYeti","1X":"Branson Air"}
}
MODEL:
public class MyCallResponse {
#SerializedName("Status")
int status;
#SerializedName("Message")
String message;
#SerializedName("Result")
Result result;
}
public class Result {
#SerializedName("0B")
String b;
#SerializedName("0Y")
String y;
#SerializedName("0X")
String x;
}
In this case, with Gson you can do:
MyCallResponse response = new Gson().fromJson(json, MyCallResponse.class);
Log.i("Response b", response.result.b);
Look at the documentation for more information about both libraries.
try this :
JSONObject json = new JSONObject(response);
JSONObject resultObj = json.getJSONObject("Result");
String OB = resultObj.getString("OB");
Try this
String base = ""; //Your json string;
JSONObject json = new JSONObject(base);
JSONOBject resultJson = json.getJSONObject("Result");
// Get all json keys "OB", "OY", "1X" etc in Result, so that we can get values against each key.
Set<Map.Entry<String, JsonElement>> entrySet = resultJson.entrySet();
Iterator iterator = entrySet.iterator();
for (int j = 0; j < entrySet.size(); j++) {
String key = null; //key = "OB", "OY", "1X" etc
try {
Map.Entry entry = (Map.Entry) iterator.next ();
key = entry.getKey ().toString ();
//key = "OB", "OY", "1X" etc
}
catch (NoSuchElementException e) {
e.printStackTrace ();
}
if (!TextUtils.isEmpty (key)) {
Log.d ("JSON_KEY", key);
String value = resultJson.getString(key);
//for key = "0B", value = "S.C. Blue Air"
//for key = "0Y", value = "FlyYeti"
//for key = "1X", value = "Branson Air"
}
}
It works with any array with dynamic json key.
Don't forget to accept the answer & upvote if it works.

JSONObject -- Retrieve Arbitrary Property

I was trying to debug the following code that can retrieve an arbitrary property of a JSONObject.
It fails when trying to access JSON more than one level deep.
For instance if the JSONObject passed in is called "node" and it has a "subnode" which has a property, it fails.
So in the example, there is an accessor "node.subnode.property".
I think what happens is that
record = ((JSONObject)record).get(key);
is returning a string -- record is not a JSONObject or JSONArray at that point.
So the next time through the for loop it doesn't find the property.
What is the best way to fix this? The method shouldn't have nay knowledge of the content of the JSONObject being accessed.
public final Object getJSONValue(JSONObject jsonObject, String accessor)
{
String[] keys = accessor.split("\\.");
Object record = jsonObject;
for (String key : keys)
{
if ((record instanceof JSONObject))
{
record = ((JSONObject)record).get(key);
}
else if ((record instanceof JSONArray))
{
record = ((JSONArray)record).get(Integer.parseInt(key));
}
else
{
return null;
}
}
return record;
}
Note that I'm using org.json.simple.JSONObject;

JSON array string to JSONArray Object in Java

I'm new to JSON manipulation in Java and I have a String in the form of a JSON Array with several layers I need to access and put into class attributes. For example, here's my JSON object:
{"JsonObject" : [{"attributeOne":"valueOne",
"attributeTwo":"valueTwo",
"attributeThree":[{"subAttributeOne":"subValueOne",
"subAttributeTwo":"subValueTwo"}],
"attributeFour":[{"subAttributeOne":"subValueThree",
"subAttributeTwo":"subValueFour"}],
"attributeFive":"valueThree"},
{"attributeOne":"valueFour",
"attributeTwo":"valueFive",
"attributeThree":[{"subAttributeOne":"subValueFive",
"subAttributeTwo":"subValueSix"}],
"attributeFour":[{"subAttributeOne":"subValueSeven",
"subAttributeTwo":"subValueEight"}],
"attributeFive":"valueSix"}]}
Lets say I have a class called MyClass that has these attributes, how would i parse this string, knowing this is an array of n Objects, each containing "attributeOne, attributeTwo, ..., attributeFive"?
Here's what I have so far:
public MyClass[] jsonToJava (String jsonObj)
{
ArrayList<MyClass> myClassArray = new ArrayList<MyClass>();
//Somehow create a JSONArray from my jsonObj String
JSONArray jsonArr = new JSONArray(jsonObj); //Don't know if this would be correct
for(int i=0; i<jsonArr.length; i++){
MyClass myClassObject = new MyClass();
myClassObject.setAttributeOne = jsonArr[i].getString("attributeOne");
// How can I access the subAttributeOne and Two under attributeThree and Four?
// add all other values to myClassObject
myClassArray.add(myClassObject);
}
return myClassArray;
}
As you can probably tell, I'm fairly new to programming :P Thanks in advance for the help!
Try Jackson JSON:
ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
User user = mapper.readValue(jsonObj, User.class); //method overloaded to take String
grabbed this two liner from:
http://wiki.fasterxml.com/JacksonInFiveMinutes
http://jackson.codehaus.org/0.9.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html
Should convert your JSON strong to an object. In a Java EE context you may be able to get this unmarshalling functionality at an endpoint with the appropriate annotation.
The way you are trying to do it is painful and involved.
I would suggest that you use a library like GSON and let it do the heavy lifting.
http://code.google.com/p/google-gson/
The documentation has object examples: https://sites.google.com/site/gson/gson-user-guide#TOC-Object-Examples
For your example you can use recursion something like:
public Object getChild(Object parent, int index) {
if (parent instanceof JSONArray) {
try {
Object o = ( (JSONArray)parent ).get(index);
if( o instanceof JSONObject ){
parent = ((JSONObject) ( o ) ).getMap();
return parent;
}
if( o instanceof Double ){
parent = (Double) o;
return parent;
}
if( o instanceof Integer ){
parent = (Integer) o;
return parent;
}
....
} catch (JSONException e1) {
e1.printStackTrace();
}
}
if (parent instanceof JSONObject) {
parent = ( (JSONObject)parent ).getMap();
}
if (parent instanceof Map<?, ?>) {
Map<?, ?> map = (Map<?, ?>) parent;
Iterator<?> it = map.keySet().iterator();
for (int i=0; i<index; i++){
it.next();
}
return map.get(it.next());
}
else if (parent instanceof Collection<?>) {
Iterator<?> it = ((Collection<?>) parent).iterator();
for (int i=0; i<index; i++){
it.next();
}
return it.next();
}
//throw new IndexOutOfBoundsException("'" + parent + "'cannot have children!");
return null;
}
But its a bit complicated (+bad practice to use instanceof) and you don't want to reinvent the wheel. So use GSON or Jackson.
Gson gson = new Gson();
String myClassStr = gson.toGson(MyClassInstance);
....
Myclass yourClass = gson.fromJson(myClassStr, Myclass.class);

How to convert from JSObject to Map (viceversa) or list JSObject members

In Javascript i have the following code:
var r=applet.foo({var0:99,var1:'foo',var2:applet});
In my Java applet i have the following:
public JSObject foo(JSObject args){
System.out.println("The function is correctly invoked");
//In fact, the following works perfectly:
System.out.println("var1 is:"+(String)args.getMember("var1"));
JSObject w=JSObject.getWindow(this);
JSObject j=(JSObject)w.eval("new Object();");
Map m=new Hashmap();
//TODO here all the keys and values of args should be added to m
m.put("hello","world");
//TODO here all the keys and values of m should be added to j
return j;
}
How can this be done? (TODOs)
Reading http://docstore.mik.ua/orelly/web/jscript/ch19_06.html, i noticed theres a getSlot method for JSObject but if i do
args.getSlot(0)
all i have is one Exception:
netscape.javascript.JSException: No such slot 0 on JavaScript object
...
Unfortunately, Errandir's solution works only when you know a name of global variable that can be used to access an object you want to get properties' names of. You need to know this name to be able to add keys method to the object, and invoke it using JSObject's call method later. Of course, you can pass a global name of your object to Java if you have it. This solution doesn't look so good especially when you can't refer to your object in global context.
As an alternative, I proposed to use this of JSObject's eval method in the comment supposing that it will do all the work. And it does. But a big disappointent was that it works as expected only in Mozilla Firefox and Opera. In Internet Explorer 9 and Google Chrome (tested under Windows 7 and Ubuntu 12.04 LTS) this of eval method always refers to applet's document window ignoring which JavaScript object JSObject instance actually represents. I don't know whether it's a bug or simply LiveConnect is supported in these browsers very poorly.
The good news is that call method of JSObject executes specified function on the proper context. Keeping that in mind I finally found a solution how a list of names of JavaScript object's properties can be retrieved. The idea is to define a temporary function in global context using eval method. This function has to receive a JavaScript object we want to get properties of and to return names of these properties as an array. After that we can invoke the temporary function through JSObject's call method passing a Java representation of concerned JavaScript object (jsObject in my method below or args as it sounds in the question). At last, temporary function can be removed.
public static ArrayList<String> getJsObjectPropertiesNames(Applet applet, JSObject jsObject) {
if (applet == null || jsObject == null)
return null;
// Retrieving global context - a JSObject representing a window applet belongs to
JSObject globalContext;
try {
globalContext = JSObject.getWindow(applet);
}
catch (JSException ex) {
return null;
}
// Checking whether passed object is not an array
try {
jsObject.getSlot(0);
return null;
}
catch (JSException e) {
}
String keysFunctionName = String.format("_getKeys%d", Calendar.getInstance().getTimeInMillis());
jsObject.eval("window['" + keysFunctionName + "'] = function(jsObject) { return Object.keys(jsObject) }");
JSObject propertiesNamesJsObject = (JSObject)globalContext.call(keysFunctionName, new Object[] { jsObject });
jsObject.eval("delete(window['" + keysFunctionName + "'])");
ArrayList<String> propertiesNames = new ArrayList<>();
try {
int slotIndex = 0;
while (true) {
Object propertyName = propertiesNamesJsObject.getSlot(slotIndex);
if (propertyName instanceof String)
propertiesNames.add((String)propertyName);
slotIndex++;
}
}
catch (JSException e) {
}
return propertiesNames;
}
As a solution, you could define method keys as proposed here (You can do it within your java-code using JSObject.eval(...)). Then you could get keys like:
JSObject keys = (JSObject)args.call("keys", Collections.EMPTY_LIST);
keys.getSlot(0);
Here below I print a String, please modify it to get whatever you need.
public final static String getKeys = "{var keys = [];for (var key in this) {keys.push(key);} keys;}";
private static String printProperties(final Object o,
final boolean printType,
final int level,
final String tab) {
final StringBuilder sb = new StringBuilder(100);
if (printType) {
sb.append("(");
sb.append(o.getClass().getSimpleName());
sb.append(") ");
}
if (o instanceof JSObject) {
sb.append("{\n");
final JSObject js = (JSObject) o;
final JSObject keys = (JSObject) js.eval(getKeys);
boolean needComma = false;
for (int i = 0;; i++) {
final String key = (String) keys.getSlot(i);
if ((key != null) && !(key.equals("undefined"))) {
final Object val = js.getMember(key);
if (!needComma) {
needComma = true;
} else {
sb.append(",\n");
}
sb.append(multitab(tab, level));
sb.append(key);
sb.append(":");
sb.append(printProperties(val, printType, level + 1, tab));
} else {
break;
}
}
sb.append("\n");
sb.append(multitab(tab, level - 1));
sb.append("}");
} else {
sb.append(o);
}
return sb.toString();
}
private final static String tab = " ";
private static String multitab(final String tab,
int i) {
final StringBuilder sb = new StringBuilder();
while (i-- > 0) {
sb.append(tab);
}
return sb.toString();
}

JSON to Java Object without creating class (PHP way)

I am dealing with json data fetched from twitter API
on PHP I normally do something like:
$data = json_decode($response);
and the $data would be STD class object
I want to do the same thing in Java.
I took a look at Gson, but I need a second argument which seems like I need to create a specific class for the fetched data.
The basic question is how can I convert JSON to Standard Java Object like in PHP (STD Class Object)
Thank You
Read it into a map using Jackson then you can access whatever data you want. For instance, if your json looks like this
{ "name":"blah",
"address": {
"line1": "1234 my street",
"city": "my city",
"state": "my state"
}
}
Then you could:
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> mystuff = mapper.readValue( jsonString, Map.class );
String name = (String)mystuff.get("name");
String city = ((Map<String, Object>)mystuff.get( "address" )).get( "city" );
If your JSON data does not follow a specific structure, don't use GSON, but a regular JSON library (like the one from json.org) that will give you an instance of a class like JSONObject, from which you can access data like jsonObject.getString("key").
There is no standard class object in Java and thus you need a class. You could dynamically create and compile the class at runtime but I doubt that's worth the trouble.
When json_encode doesn't exist on a PHP server, I use this:
<?php
if (!function_exists('json_encode'))
{
function json_encode($a=false)
{
if (is_null($a)) return 'null';
if ($a === false) return 'false';
if ($a === true) return 'true';
if (is_scalar($a))
{
if (is_float($a))
{
// Always use "." for floats.
return floatval(str_replace(",", ".", strval($a)));
}
if (is_string($a))
{
static $jsonReplaces = array(array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'), array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
return '"' . str_replace($jsonReplaces[0], $jsonReplaces[1], $a) . '"';
}
else
return $a;
}
$isList = true;
for ($i = 0, reset($a); $i < count($a); $i++, next($a))
{
if (key($a) !== $i)
{
$isList = false;
break;
}
}
$result = array();
if ($isList)
{
foreach ($a as $v) $result[] = json_encode($v);
return '[' . join(',', $result) . ']';
}
else
{
foreach ($a as $k => $v) $result[] = json_encode($k).':'.json_encode($v);
return '{' . join(',', $result) . '}';
}
}
}
?>
If you could rewrite this in Java then it should to the trick for you.
Ref:(Dead link)http://snippets.dzone.com/posts/show/7487

Categories