Json Reflaction warning with custom List - java

I am trying to reflect a json to class. But i have problem when i have JsonArray inside of JsonArray with object's. It seems that is trying to find a class like List<Step> but cannot found.
My output is :
W/System.err: Value ... at steps of type org.json.JSONArray cannot be converted to JSONObject
My class is like:
class Step {
private Consecutive consecutive;
private List<List<Steps>> steps = null;
}
a part of my Json :
{"step":{"consecutive":{"enabled":true,"period":"day"},"steps":[[{"points":100},{"points":200},{"points":300},{"points":400}],[{"points":100},{"points":200},{"points":300},{"points":400}],[{"points":100},{"points":200},{"points":300},{"points":400}],[{"points":100},{"points":200},{"points":300},{"points":400}],[{"points":100},{"points":200},{"points":300},{"points":400}],[{"points":100},{"points":200},{"points":300},{"points":400}],[{"points":100},{"points":200},{"points":300},{"points":400}]]}}
My Json Parser :
public static Object populateObjectFromJSON(Class<?> classname, JSONObject js) {
Object obj = null;
System.out.println("Populating " + classname.getSimpleName() + " -with- " + js.toString());
try {
obj = classname.newInstance();
} catch (InstantiationException e1) {
System.err.println(e1.getMessage());
return null;
} catch (IllegalAccessException e1) {
System.err.println(e1.getMessage());
return null;
}
Field[] fields;
if (privacy == 0) {
fields = classname.getFields();
} else {
fields = classname.getDeclaredFields();
}
for (Field f : fields) {
// System.out.println("Declared " + f.getName());
if ((privacy == 2) && (Modifier.isPrivate(f.getModifiers()))) {
f.setAccessible(true);
}
try {
if (js.has(f.getName())) {
String type = f.getType().getSimpleName();
if (type.equalsIgnoreCase("boolean")) {
f.setBoolean(obj, js.getBoolean(f.getName()));
} else if (type.equalsIgnoreCase("int")) {
f.setInt(obj, js.getInt(f.getName()));
} else if (type.equalsIgnoreCase("double")) {
f.setDouble(obj, js.getDouble(f.getName()));
} else if (type.equalsIgnoreCase("float")) {
f.setFloat(obj, (float) js.getDouble(f.getName()));
} else if (type.equalsIgnoreCase("string")) {
f.set(obj, js.getString(f.getName()));
} else if (f.getType().isArray()) {
f.set(obj, Array.newInstance(f.getType().getComponentType(), js.getJSONArray(f.getName()).length()));
insertArrayFromJSON(f.get(obj), js.getJSONArray(f.getName()));
}else{
f.set(obj, populateObjectFromJSON(f.getType(), js.getJSONObject(f.getName())));
}
}
} catch (IllegalArgumentException e) {
System.err.println(e.getMessage());
} catch (IllegalAccessException e) {
System.err.println(e.getMessage());
} catch (JSONException e) {
System.err.println(e.getMessage());
}
if ((privacy == 2) && (Modifier.isPrivate(f.getModifiers()))) {
f.setAccessible(false);
}
}
return obj;
}
thanks

Related

How to access the resources like string defined in string.json under element folder from the java code?

I have defined a string name and value in the string.json under the element folder. How to access those values in the java code?
Use the following Snippet to access String from strings.json
public static String getString(Context context, int id) {
String result = "";
if (context == null) {
LogUtil.error(TAG, "getString -> get null context");
return result;
}
ResourceManager manager = context.getResourceManager();
if (manager == null) {
LogUtil.error(TAG, "getString -> get null ResourceManager");
return result;
}
try {
result = manager.getElement(id).getString();
} catch (IOException e) {
LogUtil.error(TAG, "getString -> IOException");
} catch (NotExistException e) {
LogUtil.error(TAG, "getString -> NotExistException");
} catch (WrongTypeException e) {
LogUtil.error(TAG, "getString -> WrongTypeException");
}
return result;
}
and Usage would be,
String appName = getString(context, ResourceTable.String_appname);

IllegalStateException while reading response

I am reading JAVAX response using readEntity() method but I am getting following stacktrace :
java.lang.IllegalStateException: Entity input stream has already been closed.
at org.glassfish.jersey.message.internal.EntityInputStream.ensureNotClosed(EntityInputStream.java:225) ~[jersey-common.jar:?]
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:832) ~[jersey-common.jar:?]
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:785) ~[jersey-common.jar:?]
at the line
Map<String, Map> mapEntityFromResponse = res.readEntity(Map.class);
Here is my code
public Output getClaimsFromAPI(#NonNull final Input xyzInput)
throws PermanentException, TransientException {
final Response res = fetchHealBeamServiceResponse(webTarget, xyzInput);
Object respondentMapObject;
Map<String, Map> mapEntityFromResponse = res.readEntity(Map.class);
if (mapEntityFromResponse != null) {
respondentMapObject = mapEntityFromResponse.get(ServiceConstants.MAP_KEY);
return getOutputFromResponseMap(respondentMapObject, xyzInput);
} else {
throw new RuntimeException("The response returned does not contain map");
}
}
private Response fetchHealBeamServiceResponse(WebTarget healBeamTarget,
Input xyzInput)
throws PermanentException, TransientException {
Response res = null;
try {
res = healBeamTarget
.path(HealBeamServiceConstants.GET_CUSTOMER_PATH)
.register(Configurator.getSoaOpNameFeatureForCustomerResource())
.resolveTemplate(ServiceConstants.ID, xyzInput.getId())
.request(MediaType.APPLICATION_JSON_TYPE)
.property(HealBeamServiceConstants.SERVICE_KEY, SOA_SERVICE_NAME)
.property(HealBeamServiceConstants.OPERATION_KEY, SOA_OP_NAME_GET_CUSTOMER)
.acceptLanguage(java.util.Locale.getDefault())
.get();
if (Response.Status.REQUEST_TIMEOUT.getStatusCode() == res.getStatusInfo().getStatusCode()) {
throw new TransientException("Request timed out with status" + res.getStatusInfo().getStatusCode());
} else if (Response.Status.OK.getStatusCode() != res.getStatusInfo().getStatusCode()) {
log.error("Some Error"):
}
return res;
} catch (RuntimeException e) {
throw new PermanentException("Unexpected Exception Occured, Exception Message " + e.getMessage());
} finally {
if (res != null) {
res.close();
}
}
}
You are closing your response in finally right before it gets returned, that is the reason, why you can't read from it in your calling method getClaimsFromAPI().
Just to demonstrate: What do you think the method main() posted below would print?
public class NewApp {
public static void main(String[] args) {
Person p = demonstrate();
System.out.println(p.name);
}
public static Person demonstrate(){
Person person = new Person();
try {
person.name = "name set in try";
return person;
} catch (Exception ex) {
throw ex;
} finally {
person.name = "name set in finally";
}
}
}
class Person {
public String name;
}

getDeclaredMethod not working in android 9(PIE)

public RefStaticMethod(Class<?> cls, Field field) {
try {
if (field.isAnnotationPresent(MethodParams.class)) {
Class<?>[] types = field.getAnnotation(MethodParams.class).value();
for (int i = 0; i < types.length; i++) {
Class<?> clazz = types[i];
if (clazz.getClassLoader() == getClass().getClassLoader()) {
try {
Class.forName(clazz.getName());
Class<?> realClass = (Class<?>) clazz.getField("TYPE").get(null);
types[i] = realClass;
} catch (Throwable e){
Log.e("hello", "RefStaticMethod: 1" );
throw new RuntimeException(e);
}
}
}
this.method = cls.getDeclaredMethod(field.getName(), types);
this.method.setAccessible(true);
} else if (field.isAnnotationPresent(MethodReflectParams.class)) {
boolean arrayset = false;
String[] typeNames = field.getAnnotation(MethodReflectParams.class).value();
Class<?>[] types = new Class<?>[typeNames.length];
Class<?>[] types2 = new Class<?>[typeNames.length];
for (int i = 0; i < typeNames.length; i++) {
Class<?> type = getProtoType(typeNames[i]);
if (type == null) {
try {
type = Class.forName(typeNames[i]);
} catch (ClassNotFoundException e) {
Log.e("hello", "RefStaticMethod: 2" );
e.printStackTrace();
}
}
types[i] = type;
if ("java.util.HashSet".equals(typeNames[i])) {
arrayset = true;
Class<?> type2 = type;
try {
type2 = Class.forName("android.util.ArraySet");
} catch (ClassNotFoundException e) {
Log.e("hello", "RefStaticMethod: 3" );
e.printStackTrace();
}
if (type2 != null) {
types2[i] = type2;
} else {
types2[i] = type;
}
} else {
types2[i] = type;
}
}
try {
this.method = cls.getDeclaredMethod(field.getName(), types);
} catch (Exception e) {
Log.e("hello", "RefStaticMethod: 4 "+e.toString() );
e.printStackTrace();
if (arrayset) {
this.method = cls.getDeclaredMethod(field.getName(), types2);
}
}
this.method.setAccessible(true);
} else {
for (Method method : cls.getDeclaredMethods()) {
if (method.getName().equals(field.getName())) {
this.method = method;
this.method.setAccessible(true);
break;
}
}
}
if (this.method == null) {
throw new NoSuchMethodException(field.getName());
}
}
catch(Exception e)
{
Log.e("hello", "RefStaticMethod: 5 "+e.toString());
}
}
Logcat error:
2019-07-02 03:01:01.893 29833-29861/io.virtualapp:x E/hello:
RefStaticMethod: 4 java.lang.NoSuchMethodException:
collectCertificates [class android.content.pm.PackageParser$Package,
int] 2019-07-02 03:01:01.896 29833-29861/io.virtualapp:x E/hello:
RefStaticMethod: 5 java.lang.NullPointerException: Attempt to invoke
virtual method 'void java.lang.reflect.Method.setAccessible(boolean)'
on a null object reference
have any solution for android 9(PIE) or any alternative way to resolve this issue of getDeclaredMethod. thanks in advance

How to properly return a string from a method with try and catch

Every time I called this method it always return null even if the value of userProfile.get("facebookId") is not null.
public String updateProfilePicture() {
String facebookId = null;
if (currentUser.get("profile") != null) {
JSONObject userProfile = currentUser.getJSONObject("profile");
try {
if (userProfile.getString("facebookId") != null) {
facebookId = userProfile.get("facebookId").toString();
} else {
facebookId = null;
}
} catch (JSONException e) {
// handle error
facebookId = null;
}
}
return facebookId;
}

How to serialize object to CSV file?

I want to write a Object into CSV file.
For XML we have XStream like this
So if i want to convert object to CSV do we have any such library ?
EDIT:
I want to pass my list of Bean to a method which should write all the fields of bean to CSV.
First, serialization is writing the object to a file 'as it is'. AFAIK, you cannot choose file formats and all. The serialized object (in a file) has its own 'file format'
If you want to write the contents of an object (or a list of objects) to a CSV file, you can do it yourself, it should not be complex.
Looks like Java CSV Library can do this, but I have not tried this myself.
EDIT: See following sample. This is by no way foolproof, but you can build on this.
//European countries use ";" as
//CSV separator because "," is their digit separator
private static final String CSV_SEPARATOR = ",";
private static void writeToCSV(ArrayList<Product> productList)
{
try
{
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("products.csv"), "UTF-8"));
for (Product product : productList)
{
StringBuffer oneLine = new StringBuffer();
oneLine.append(product.getId() <=0 ? "" : product.getId());
oneLine.append(CSV_SEPARATOR);
oneLine.append(product.getName().trim().length() == 0? "" : product.getName());
oneLine.append(CSV_SEPARATOR);
oneLine.append(product.getCostPrice() < 0 ? "" : product.getCostPrice());
oneLine.append(CSV_SEPARATOR);
oneLine.append(product.isVatApplicable() ? "Yes" : "No");
bw.write(oneLine.toString());
bw.newLine();
}
bw.flush();
bw.close();
}
catch (UnsupportedEncodingException e) {}
catch (FileNotFoundException e){}
catch (IOException e){}
}
This is product (getters and setters hidden for readability):
class Product
{
private long id;
private String name;
private double costPrice;
private boolean vatApplicable;
}
And this is how I tested:
public static void main(String[] args)
{
ArrayList<Product> productList = new ArrayList<Product>();
productList.add(new Product(1, "Pen", 2.00, false));
productList.add(new Product(2, "TV", 300, true));
productList.add(new Product(3, "iPhone", 500, true));
writeToCSV(productList);
}
Hope this helps.
Cheers.
For easy CSV access, there is a library called OpenCSV. It really ease access to CSV file content.
EDIT
According to your update, I consider all previous replies as incorrect (due to their low-levelness). You can then go a completely diffferent way, the hibernate way, in fact !
By using the CsvJdbc driver, you can load your CSV files as JDBC data source, and then directly map your beans to this datasource.
I would have talked to you about CSVObjects, but as the site seems broken, I fear the lib is unavailable nowadays.
Two options I just ran into:
http://sojo.sourceforge.net/
http://supercsv.sourceforge.net/
It would be interesting to have a csv serializer as it would take up the minimal space compared to other serializing method.
The closest support for java object to csv is stringutils provided by spring utils project
arrayToCommaDelimitedString(Object[] arr) but it is far from being a serializer.
Here is a simple utility which uses reflection to serialize value objects
public class CSVWriter
{
private static String produceCsvData(Object[] data) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
if(data.length==0)
{
return "";
}
Class classType = data[0].getClass();
StringBuilder builder = new StringBuilder();
Method[] methods = classType.getDeclaredMethods();
for(Method m : methods)
{
if(m.getParameterTypes().length==0)
{
if(m.getName().startsWith("get"))
{
builder.append(m.getName().substring(3)).append(',');
}
else if(m.getName().startsWith("is"))
{
builder.append(m.getName().substring(2)).append(',');
}
}
}
builder.deleteCharAt(builder.length()-1);
builder.append('\n');
for(Object d : data)
{
for(Method m : methods)
{
if(m.getParameterTypes().length==0)
{
if(m.getName().startsWith("get") || m.getName().startsWith("is"))
{
System.out.println(m.invoke(d).toString());
builder.append(m.invoke(d).toString()).append(',');
}
}
}
builder.append('\n');
}
builder.deleteCharAt(builder.length()-1);
return builder.toString();
}
public static boolean generateCSV(File csvFileName,Object[] data)
{
FileWriter fw = null;
try
{
fw = new FileWriter(csvFileName);
if(!csvFileName.exists())
csvFileName.createNewFile();
fw.write(produceCsvData(data));
fw.flush();
}
catch(Exception e)
{
System.out.println("Error while generating csv from data. Error message : " + e.getMessage());
e.printStackTrace();
return false;
}
finally
{
if(fw!=null)
{
try
{
fw.close();
}
catch(Exception e)
{
}
fw=null;
}
}
return true;
}
}
Here is an example value object
public class Product {
private String name;
private double price;
private int identifier;
private boolean isVatApplicable;
public Product(String name, double price, int identifier,
boolean isVatApplicable) {
super();
this.name = name;
this.price = price;
this.identifier = identifier;
this.isVatApplicable = isVatApplicable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(long price) {
this.price = price;
}
public int getIdentifier() {
return identifier;
}
public void setIdentifier(int identifier) {
this.identifier = identifier;
}
public boolean isVatApplicable() {
return isVatApplicable;
}
public void setVatApplicable(boolean isVatApplicable) {
this.isVatApplicable = isVatApplicable;
}
}
and the code to run the util
public class TestCSV
{
public static void main(String... a)
{
Product[] list = new Product[5];
list[0] = new Product("dvd", 24.99, 967, true);
list[1] = new Product("pen", 4.99, 162, false);
list[2] = new Product("ipad", 624.99, 234, true);
list[3] = new Product("crayons", 4.99,127, false);
list[4] = new Product("laptop", 1444.99, 997, true);
CSVWriter.generateCSV(new File("C:\\products.csv"),list);
}
}
Output:
Name VatApplicable Price Identifier
dvd true 24.99 967
pen false 4.99 162
ipad true 624.99 234
crayons false 4.99 127
laptop true 1444.99 997
I wrote a simple class that uses OpenCSV and has two static public methods.
static public File toCSVFile(Object object, String path, String name) {
File pathFile = new File(path);
pathFile.mkdirs();
File returnFile = new File(path + name);
try {
CSVWriter writer = new CSVWriter(new FileWriter(returnFile));
writer.writeNext(new String[]{"Member Name in Code", "Stored Value", "Type of Value"});
for (Field field : object.getClass().getDeclaredFields()) {
writer.writeNext(new String[]{field.getName(), field.get(object).toString(), field.getType().getName()});
}
writer.flush();
writer.close();
return returnFile;
} catch (IOException e) {
Log.e("EasyStorage", "Easy Storage toCSVFile failed.", e);
return null;
} catch (IllegalAccessException e) {
Log.e("EasyStorage", "Easy Storage toCSVFile failed.", e);
return null;
}
}
static public void fromCSVFile(Object object, File file) {
try {
CSVReader reader = new CSVReader(new FileReader(file));
String[] nextLine = reader.readNext(); // Ignore the first line.
while ((nextLine = reader.readNext()) != null) {
if (nextLine.length >= 2) {
try {
Field field = object.getClass().getDeclaredField(nextLine[0]);
Class<?> rClass = field.getType();
if (rClass == String.class) {
field.set(object, nextLine[1]);
} else if (rClass == int.class) {
field.set(object, Integer.parseInt(nextLine[1]));
} else if (rClass == boolean.class) {
field.set(object, Boolean.parseBoolean(nextLine[1]));
} else if (rClass == float.class) {
field.set(object, Float.parseFloat(nextLine[1]));
} else if (rClass == long.class) {
field.set(object, Long.parseLong(nextLine[1]));
} else if (rClass == short.class) {
field.set(object, Short.parseShort(nextLine[1]));
} else if (rClass == double.class) {
field.set(object, Double.parseDouble(nextLine[1]));
} else if (rClass == byte.class) {
field.set(object, Byte.parseByte(nextLine[1]));
} else if (rClass == char.class) {
field.set(object, nextLine[1].charAt(0));
} else {
Log.e("EasyStorage", "Easy Storage doesn't yet support extracting " + rClass.getSimpleName() + " from CSV files.");
}
} catch (NoSuchFieldException e) {
Log.e("EasyStorage", "Easy Storage fromCSVFile failed.", e);
} catch (IllegalAccessException e) {
Log.e("EasyStorage", "Easy Storage fromCSVFile failed.", e);
}
} // Close if (nextLine.length >= 2)
} // Close while ((nextLine = reader.readNext()) != null)
} catch (FileNotFoundException e) {
Log.e("EasyStorage", "Easy Storage fromCSVFile failed.", e);
} catch (IOException e) {
Log.e("EasyStorage", "Easy Storage fromCSVFile failed.", e);
} catch (IllegalArgumentException e) {
Log.e("EasyStorage", "Easy Storage fromCSVFile failed.", e);
}
}
I think with some simple recursion these methods could be modified to handle any Java object, but for me this was adequate.
Though its very late reply, I have faced this problem of exporting java entites to CSV, EXCEL etc in various projects, Where we need to provide export feature on UI.
I have created my own light weight framework. It works with any Java Beans, You just need to add annotations on fields you want to export to CSV, Excel etc.
Link: https://github.com/abhisoni96/dev-tools
Worth mentioning that the handlebar library https://github.com/jknack/handlebars.java can trivialize many transformation tasks include toCSV.
You can use gererics to work for any class
public class FileUtils<T> {
public String createReport(String filePath, List<T> t) {
if (t.isEmpty()) {
return null;
}
List<String> reportData = new ArrayList<String>();
addDataToReport(t.get(0), reportData, 0);
for (T k : t) {
addDataToReport(k, reportData, 1);
}
return !dumpReport(filePath, reportData) ? null : filePath;
}
public static Boolean dumpReport(String filePath, List<String> lines) {
Boolean isFileCreated = false;
String[] dirs = filePath.split(File.separator);
String baseDir = "";
for (int i = 0; i < dirs.length - 1; i++) {
baseDir += " " + dirs[i];
}
baseDir = baseDir.replace(" ", "/");
File base = new File(baseDir);
base.mkdirs();
File file = new File(filePath);
try {
if (!file.exists())
file.createNewFile();
} catch (Exception e) {
e.printStackTrace();
return isFileCreated;
}
try (BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(file), System.getProperty("file.encoding")))) {
for (String line : lines) {
writer.write(line + System.lineSeparator());
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
void addDataToReport(T t, List<String> reportData, int index) {
String[] jsonObjectAsArray = new Gson().toJson(t).replace("{", "").replace("}", "").split(",\"");
StringBuilder row = new StringBuilder();
for (int i = 0; i < jsonObjectAsArray.length; i++) {
String str = jsonObjectAsArray[i];
str = str.replaceFirst(":", "_").split("_")[index];
if (i == 0) {
if (str != null) {
row.append(str.replace("\"", ""));
} else {
row.append("N/A");
}
} else {
if (str != null) {
row.append(", " + str.replace("\"", ""));
} else {
row.append(", N/A");
}
}
}
reportData.add(row.toString());
}

Categories