How to not use nested try catch blocks when parsing JSON? - java

Is there a more elegant solution to my code below than to have multiple nested try-catch blocks for JSONException?
The reason I nest them is because I don't want to rest of the parsing to stop if there is one error in parsing. I want each to be independent of each other.
if (obj.has(GlobalVars.KEY_DESC)) {
try {
JSONObject descObj = obj.getJSONObject(GlobalVars.KEY_DESC);
if (descObj.has(GlobalVars.KEY_COUNTRY)) {
try {
description.put(GlobalVars.KEY_COUNTRY, descObj.getString(GlobalVars.KEY_COUNTRY));
}
catch (JSONException e) { e.printStackTrace(); }
}
if (descObj.has(GlobalVars.KEY_CITY)) {
try {
description.put(GlobalVars.KEY_COUNTRY, descObj.getString(GlobalVars.KEY_CITY));
}
catch (JSONException e) { e.printStackTrace(); }
}
if (descObj.has(GlobalVars.KEY_POSTAL)) {
try {
description.put(GlobalVars.KEY_COUNTRY, descObj.getString(GlobalVars.KEY_POSTAL));
}
catch (JSONException e) { e.printStackTrace(); }
}
if (descObj.has(GlobalVars.KEY_STREET)) {
try {
description.put(GlobalVars.KEY_COUNTRY, descObj.getString(GlobalVars.KEY_STREET));
}
catch (JSONException e) { e.printStackTrace(); }
}
if (descObj.has(GlobalVars.KEY_SUBSTREET)) {
try {
description.put(GlobalVars.KEY_COUNTRY, descObj.getString(GlobalVars.KEY_SUBSTREET));
}
catch (JSONException e) { e.printStackTrace(); }
}
if (descObj.has(GlobalVars.KEY_YEAR)) {
try {
description.put(GlobalVars.KEY_COUNTRY, descObj.getInt(GlobalVars.KEY_YEAR));
}
catch (JSONException e) { e.printStackTrace(); }
}
if (descObj.has(GlobalVars.KEY_SQUARE_METERS)) {
try {
description.put(GlobalVars.KEY_COUNTRY, descObj.getInt(GlobalVars.KEY_SQUARE_METERS));
}
catch (JSONException e) { e.printStackTrace(); }
}
}
catch (JSONException e) { e.printStackTrace(); }
}

You seems to be doing similar stuff in all of your if statements:
try {
description.put(GlobalVars.KEY_COUNTRY, descObj.getString(GlobalVars.KEY_COUNTRY));
}
catch (JSONException e) { e.printStackTrace(); }
So you can move this code to a method and can call that method from each if statement. It will make your code cleaner

I think you don't need to use all these try catch if you use Gson lib, it ignored missing fields and continue the parsing, but you can register the missing fields by using the below code:
package json;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
public class App {
public static void main(String[] args) {
Gson gson = new GsonBuilder().registerTypeAdapter(
MyAnnotationBean.class,
new AnnotatedDeserializer<MyAnnotationBean>()).create();
String json = "{\"desc\":\"This is desc\",\"country\":\"this is country\"}";
MyAnnotationBean tab = gson.fromJson(json, MyAnnotationBean.class);
System.out.println(tab.desc);
System.out.println(tab.country);
json = "{\"desc\":\"This is desc\"}";
tab = gson.fromJson(json, MyAnnotationBean.class);
System.out.println(tab.desc);
System.out.println(tab.country);
json = "{\"country\":\"This is country\"}";
tab = gson.fromJson(json, MyAnnotationBean.class);
System.out.println(tab.desc);
System.out.println(tab.country);
}
}
class MyAnnotationBean {
public String desc;
public String country;
}
class AnnotatedDeserializer<T> implements JsonDeserializer<T> {
public T deserialize(JsonElement je, Type type,
JsonDeserializationContext jdc) throws JsonParseException {
T obj = new Gson().fromJson(je, type);
Field[] fields = obj.getClass().getDeclaredFields();
for (Field f : fields) {
try {
f.setAccessible(true);
if (f.get(obj) == null) {
// throw new JsonParseException("required json " +
// f.getName());
// add your code to know missing fields
}
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
}
return obj;
}
}

Related

Is there a way to get a generic mp3 tag using mp3agic?

I'm developing an MP3 player with java, using mp3agic to edit .mp3 files metadata. The problem is: I don't know the specific tags of the files to edit the desired data.
Here's my code to get the mp3 track for example:
public static int get_rep(Music msc)
{
try
{
Mp3File file = new Mp3File(msc.get_path());
if (file.hasId3v1Tag())
{
ID3v1 tag = file.getId3v1Tag();
return Integer.parseInt(tag.getTrack());
}
else if (file.hasId3v2Tag())
{
ID3v2 tag = file.getId3v2Tag();
return Integer.parseInt(tag.getTrack());
}
}
catch (UnsupportedTagException e)
{
e.printStackTrace();
}
catch (InvalidDataException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return -1;
}
Is there a way to get the tag value skipping file.hasId3v1Tag() and file.hasId3v2Tag() verifications?
I tried:
private static Object get_tag(Music msc)
{
try
{
Mp3File file = new Mp3File(msc.get_path());
if (file.hasId3v1Tag())
{
return file.getId3v1Tag();
}
else if (file.hasId3v2Tag())
{
return file.getId3v2Tag();
}
/*
else if(file.hasCustomTag())
{
file.removeCustomTag();
return file.getCustomTag();
}
*/
}
catch (UnsupportedTagException e)
{
e.printStackTrace();
}
catch (InvalidDataException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return Boolean.FALSE;
}
But I still have to check the tags, then cast the Object value to a tag value, which means I'd have to know it anyway. I'm accepting any suggestions, even exchanging mp3agic.
ID3v2 extends ID3v1, so you should be able to use ID3v1 tag = file.getId3v2Tag(); and be able to extract ID3v1 data from it.
You could try this:
private static ID3v1 get_tag(Music msc) {
try {
Mp3File file = new Mp3File(msc.get_path());
if (file.hasId3v1Tag()) {
return file.getId3v1Tag();
} else if (file.hasId3v2Tag()) {
return file.getId3v2Tag();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

Jackson can't parse json, returns NPE

I'm trying to parse json (steam webchat) which looks like that (I've changed response cause I don't wanna show the data):
/**/({
"pollid": 00,
"messages": [
{
"type": "personastate",
"timestamp": 0000000000,
"utc_timestamp": 000000000,
"steamid_from": "000000000000",
"status_flags": 0000000,
"persona_state": 0,
"persona_name": "asd"
}
]
,
"messagelast": 00,
"timestamp": 0000000000,
"utc_timestamp": 000000000000,
"messagebase": 00,
"sectimeout": 0,
"error": "OK"
})
And my parsing class looks like that:
package jsonRequest;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
public class NewMessageJson {
public Integer poollid;
private String lastMessageId;
private String error;
private String messageBase;
public NewMessageJson(String response) {
response = response.substring(response.indexOf("{"),
response.indexOf("}") + 1); // cut off comment block
JsonFactory factory = new JsonFactory();
JsonParser jp = null;
try {
jp = factory.createJsonParser(response);
} catch (JsonParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
if (jp.nextToken() != JsonToken.START_OBJECT) {
throw new IOException("Server didn't return any data");
}
while (jp.nextToken() != JsonToken.END_OBJECT) {
String fieldName = jp.getCurrentName();
jp.nextToken();
if (fieldName.equals("messagelast")) {
setLastMessageId(jp.getText());
} else if (fieldName.equals("pollid")) {
setPoollid(jp.getIntValue());
} else if (fieldName.equals("messagebase")) {
setMessageBase(jp.getText());
} else if (fieldName.equals("error")) {
setError(jp.getText());
}
}
jp.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
jp.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Integer getPoollid() {
return poollid;
}
public void setPoollid(Integer poollid) {
this.poollid = poollid;
}
public String getLastMessageId() {
return lastMessageId;
}
public void setLastMessageId(String lastMessageId) {
this.lastMessageId = lastMessageId;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getMessageBase() {
return messageBase;
}
public void setMessageBase(String messageBase) {
this.messageBase = messageBase;
}
}
And when it comes to the line
if (fieldName.equals("messagelast")) {
It crashes and returns NPE.
I have 3 other classes looking exactly like this one and everything works perfectly.
I am pretty sure the reason you are getting the NPE is because you initially instantiate JsonParser jp as null. You assign it to factory.createJsonParser(response) in your try block but do not deal with the error in any way besides printing the stack trace. If there was an error executing factory.createJsonParser(response), you need to make sure nothing else runs.
I would suggest changing your code to this:
...
JsonFactory factory = new JsonFactory();
JsonParser jp = null;
try {
jp = factory.createJsonParser(response);
} catch (JsonParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
System.out.println("There was an error while setting jp to factory.createJsonParser(response). Error message is: " + e1.getMessage());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
System.out.println("There was an error while setting jp to factory.createJsonParser(response). Error message is: " + e1.getMessage());
}
if(jp != null) {
try {
if (jp.nextToken() != JsonToken.START_OBJECT) {
throw new IOException("Server didn't return any data");
}
while (jp.nextToken() != JsonToken.END_OBJECT) {
String fieldName = jp.getCurrentName();
jp.nextToken();
if (fieldName.equals("messagelast")) {
setLastMessageId(jp.getText());
} else if (fieldName.equals("pollid")) {
setPoollid(jp.getIntValue());
} else if (fieldName.equals("messagebase")) {
setMessageBase(jp.getText());
} else if (fieldName.equals("error")) {
setError(jp.getText());
}
}
jp.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
jp.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
...
This way, you can avoid all NPEs!
EDIT: You should also implement what peeskillet suggested

Java handle errors & exceptions

I have a class that allows to download a file from the internet:
public String download(String URL) {
try {
if(somethingbad) {
// set an error?
return false;
}
}
//...
catch (SocketException e) {
e.printStackTrace();
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
catch (ClientProtocolException e) {
e.printStackTrace();
}
catch(InterruptedIOException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
Now, I am calling this function in another class and i want to show a message that will help me figure out why this will not work.
what can i do to display something like this?
HTTPReq r = new HTTPReq("http://www.stack.com/api.json");
if(r.err) {
showMessage(getMessage());
}
and the getMessage() will return the SocketException or IOException or even "empty url" if the URL is empty.
First of all I do not think you need all these:
SocketException, UnsupportedEncodingException, ClientProtocolException since they extend IOException
but if you want you can do this:
public String download(String URL) throws IOException, Exception {
try {
if(somethingbad) {
throws new Exception("My Message);
}
}
catch (IOException e) {
throw e;
}
}
And then in your other file:
try {
// some stuff
}
catch (Exception e) {
// do something with e.getMessage();
}
catch (IOException e) {
// do something with e.getMessage();
}
Instead of just doing e.printStackTrace() inside the catch blocks, throw the exception back like so:
throw e;
Then you can surround the calling code like so:
try {
HTTPReq r = new HTTPReq("http://www.stack.com/api.json");
} catch (Exception e) {
// Show error message
}

playframework 2.2.1 ebean how to use java refection update entity

I am new to Play framework & ebean
And want make a common util function to update my Model's instance
so I used following code:
private static void updateEntity(Class cls, Long id, ObjectNode data){
Object instance = Ebean.find(cls,id);
for (Field field :cls.getFields()){
String fieldName = field.getName();
if (!fieldName.equals("id")){
field.setAccessible(true);
try {
field.set(instance, data.get(fieldName).toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
try {
//not work
cls.getMethod("save").invoke(instance);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//not work too
//Ebean.save(instance);
}
I call it by using:
Long id = 1L;
Class cls = MyEntity.class;
ObjectNode data = Json.newObject();
data.put("name","Hello world");
data.put("id",1L);
updateEntity(cls,id,data);
MyEntity is a nomarl entity class for model which contains id and name
So , How do I do next?
private static void updateEntity(Class cls, Long id, ObjectNode data){
User user = Ebean.find(cls,id); // For example, consider Ebean returns 'User' object. You can mention your Model here.
try{
user.getClass().getDeclaredField("id").set(user, data.get("id").toString());
}
catch(NoSuchFieldException exception){
exception.printStackTrace(); // If no field is found in the name of `id`.
}
catch(NullPointerException exception){
exception.printStackTrace(); // If field name is null
}
catch(Exception exception){
exception.printStackTrace();
}
user.save();
}

ActiveMQ: How to get all messages in a queue for Receiver (Java)

Here is the Server's code:
import java.net.UnknownHostException;
import java.io.IOException;
import org.apache.activemq.transport.stomp.StompConnection;
public class Server{
public static void main(String[] args) {
try {
StompConnection con = new StompConnection();
con.open("localhost", 61618);
con.connect("admin", "admin123");
con.begin("a1");
con.send("/queue/test1", "This is test message 1");
con.send("/queue/test1", "This is test message 2");
con.send("/queue/test1", "This is test message 3");
con.commit("a1");
con.disconnect();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is the Client's code:
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Scanner;
import org.apache.activemq.transport.stomp.StompConnection;
import org.apache.activemq.transport.stomp.StompFrame;
import org.apache.activemq.transport.stomp.Stomp.Headers.Subscribe;
public class Client {
public static void main(String[] args) {
try {
//login.
Scanner in = new Scanner(System.in);
System.out.print("Password: ");
String pass = in.next();
if (!"123".equals(pass)){
System.out.println("Sorry, wrong password.");
}
else
{
StompConnection con= new StompConnection();
con.open("localhost", 61618);
con.connect("admin", "admin123");
con.subscribe("/queue/test1", Subscribe.AckModeValues.CLIENT);
con.begin("a2");
StompFrame mes = con.receive();
System.out.println(mes.getBody());
con.ack(message, "a2");
con.commit("a2");
con.disconnect();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
I have 3 messages on Server. However, I only can get 1 message per time in Client. How to get all the messages in the queue in a run? Anyone can help me?
Not entirely sure what you've tried here but to read all three is just a simple loop like:
con.begin("a2");
while (true) {
StompFrame message = null;
try {
message = connection.receive(5000);
} catch (Exception e) {
break;
}
System.out.println(mes.getBody());
con.ack(message, "a2");
}
connection.commit("a2");

Categories