Gson deserialize with null int can't seems to work - java

When i download data on the web, sometimes it works and sometime it doesn't.
And my problem is in one int :
runtime: ""
runtime is an int and when i use gson on it can cause this problem :
01-07 21:22:57.602: E/AndroidRuntime(2726): Caused by: java.lang.NumberFormatException: Invalid int: ""
and i tried to some if statement but it doesn't work.
public int getRuntime() {
if(Integer.valueOf(runtime)==null){
return 0;
}else{
return runtime;
}
}
or even
public int getRuntime() {
if(Integer.valueOf(runtime).equals(null)){
return 0;
}else{
return runtime;
}
}
but nothing works.

Integer.valueOf() expects a String representing an integer. Calling it with an empty string will lead to an exception. You need to test the String before parsing it as an integer:
int runtime;
if ("".equals(string)) {
runtime = 0;
}
else {
runtime = Integer.parseInt(string);
}
or, if you always want that runtime is 0 if the string is not a valid integer, then catch the exception:
try {
runtime = Integer.parseInt(string);
}
catch (NumberFormatException e) {
runtime = 0;
}
Now, it it's gson that parses the string for you, and this string is not always an integer, then the runtime field should not be an int, but a String. And you should parse it yourself, as shown above.
Given your question, before trying to do anything with gson and android, you should learn the basics of the Java language. You don't seem to understand the type system in Java and what exceptions are. Read http://docs.oracle.com/javase/tutorial/java/nutsandbolts/

Handle the runtime as a string, declare it as a string in the class where you are deserializing.
Then using the gson like this will handle the nulls correctly
Gson gson = new GsonBuilder().serializeNulls().create();
This works also when serializing, normally if values are null it will just not put anything in the json to serialize.

It looks like you don't understand what exceptions are, or how to handle them:
http://docs.oracle.com/javase/tutorial/essential/exceptions
public int getRuntime() {
int i = 0;
try {
i = Integer.valueOf(runtime);
} catch (NumberFormatException e) {
System.out.println("runtime wasn't an int, returning 0");
}
return i;
}
Hint: whatever runtime is, it's not anything that can be converted to an int. From what you posted, it looks like an empty String

You either need to check runtime first, e.g. if( runtime.isEmpty() ) or yet better - using apache commons lang - if( StringUtils.isBlank( runtime )) or catch the NumberFormatException that is thrown.

Related

Saxon-HE Java Extension - How to I access the value of a xsl-variable which is passed as a parameter?

I have created a function using the Saxon documentation which has 3 parameters. The function takes an input string and pads it out to a specific size using an integer and string values.
padStringLeft(inputStr,size,padChar)
If I put this in my XSLT and hard wire the parameters the function works.
<debug1><xsl:value-of select="c4j_XSLT_Ext_padStringLeft:padStringLeft('1',4,'0')" /></debug1>
The output from the above would be '0001'
When I pass the contents of a XSLT variable however and set a debug / break point in my java function I can see that I'm getting param0 as a lazysequence.
<debug2><xsl:value-of select="c4j_XSLT_Ext_padStringLeft:padStringLeft($myvar,4,'0')" /></debug2>
Java function
As my code is attempting to treat it as a string it does not work.
How should I be handling this scenario, how do I access the value or the xsl-variable/param and what if sometimes I want to use a literal string instead of a variable?
public class XSLT_Ext_padStringLeft extends ExtensionFunctionDefinition
{
#Override
public SequenceType[] getArgumentTypes()
{
return new SequenceType[]{SequenceType.SINGLE_STRING,SequenceType.SINGLE_INTEGER, SequenceType.SINGLE_STRING};
}
#Override
public StructuredQName getFunctionQName()
{
return new StructuredQName("c4j_XSLT_Ext_padStringLeft", "http://com.commander4j.Transformation.XSLT_Ext_padStringLeft", "padStringLeft");
}
#Override
public SequenceType getResultType(SequenceType[] arg0)
{
return SequenceType.SINGLE_STRING;
}
#Override
public ExtensionFunctionCall makeCallExpression()
{
return new ExtensionFunctionCall() {
#Override
public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
String inputStr;
try
{
inputStr = ((StringValue)arguments[0]).getStringValue();
} catch (ClassCastException ex)
{
inputStr = "";
}
long size;
try
{
String temp =arguments[1].toString();
size = Integer.valueOf(temp);
} catch (ClassCastException ex)
{
size = 1;
}
String padStr;
try
{
padStr = ((StringValue)arguments[2]).getStringValue();
} catch (ClassCastException ex)
{
padStr = "";
}
String result = inputStr;
while (result.length() < size)
{
result = padStr + result;
}
return StringValue.makeStringValue(result);
}
};
}
}
Thanks
Dave
In general the parameters are passed as instance of the class net.sf.saxon.om.Sequence, and you should only use the methods on the interface Sequence, rather than examining what particular kind of Sequence it is, because that could change in the future.
If you're expecting a singleton sequence (that is, a single item), call head() to get the first item in the sequence (this will return null if the sequence is empty). You will then have an instance of net.sf.saxon.om.Item. (The Sequence might already be an Item, because an item is a sequence, but you can't rely on that, and calling head() is safer than casting.) If you're expecting a string, you can safely call getStringValue() on this item to get the value as a string.
Also note, Saxon uses lazy evaluation wherever possible, which means that the string might not actually be computed until someone asks for its value. This means that innocent-looking calls like head() and getStringValue() can actually throw exceptions, and you need to be prepared for this.
So in short, you should replace
inputStr = ((StringValue)arguments[0]).getStringValue();
with
inputStr = arguments[0].head().getStringValue();
Also note, Saxon uses lazy evaluation wherever possible, which means that the string might not actually be computed until someone asks for its value. This means that innocent-looking calls like head() and getStringValue() can actually throw exceptions, and you need to be prepared for this.
So if I understand you correctly - when I call Transform to process the XSLT transformation it will call each of my custom java external functions as needed but the reference to
inputStr = arguments[0].head().getStringValue();
could generate an exception?
I would then need to do something within the java function to force it to get the value - or would I let the exception propogate back to the calling Transformation and catch it there ?
Dave

Can Optional be used to as alternative to catch ConversionException

How to refactor the following code of reading properties file, so that it returns int, double or String depending on the read value?
public static <T> T readFromConfig(String keyName) {
PropertiesConfiguration config = new PropertiesConfiguration();
String propertiesFilePath = "src/main/resources/application.properties";
try {
config.load(propertiesFilePath);
try {
Integer value = config.getInt(keyName);
return (T) value;
} catch (ConversionException notInteger) {
try {
Double value = config.getDouble(keyName);
return (T) value;
} catch (ConversionException notDouble) {
return (T) config.getString(keyName);
}
}
} catch (ConfigurationException e) {
logger.warn("Could not parse " + propertiesFilePath);
return (T) "";
}
}
As the author figured himself: Optional<> isn't an option here, because, as the other answer shows: it would result in returning Optional<Object> which gives even less type information.
But honestly, from a clean code perspective, even the idea of
public static <T> T readFromConfig(String keyName) {
is kinda flawed. What does that method buy? Nothing. Because the caller says: I expect an Integer to come back, but you push back a Double or even String. You see, the compiler gets told "the method should return Integer, or Double, ...", and then it sees: "yes, possible". But that is totally decoupled from what happens at runtime.
If you go:
Integer intVal = readFromConfig("keyPointingToDoubleValue");
the compiler will not complain. Because it sees: you want an Integer; and hey, the method can return an Integer.
At runtime? When the value is retrieved, and isn't an Integer, a Double or String is returned. No idea what will happen here (class cast exception, or maybe some stack violation). But it should not work at runtime.
So, the real solution goes like this:
Either you have multiple methods, such as:
public static Integer readIntegerFromConfig(String keyName) throws SomeException ...
public static Integer readIntegerFromConfig(String keyName, Integer Default) throws SomeException ...
Or maybe:
public static Object readFromConfig(String keyName) {
or
public static <T> T readFromConfig(String keyName, T default)
In other words: you want an API that allows users of it to really say what they want, and always give them what they want. Or you totally avoid distinct types on that level, and return Strings, and have the client code make conversions.
Your current approach, as said: buys you nothing, at the cost of a misleading, complicated API.
Here is what I can suggest you also this is a clear violation of Single Responsibility Principle (SRP) as it tries to convert to three different types which should be avoided for cleaner code :
public static Optional<Object> readFromConfig(String keyName) {
PropertiesConfiguration config = new PropertiesConfiguration();
String propertiesFilePath = "src/main/resources/opf.properties";
try {
config.load(propertiesFilePath);
return Stream.<Supplier<Optional>>of(
() -> Optional.of(config.getInt(keyName)),
() -> Optional.of(config.getDouble(keyName)),
() -> Optional.of(config.getString(keyName)))
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
} catch (Exception e) {
return Optional.empty();
}
}
So, that's the end of deiscussion.
The answer for question "Can Optional be used to as alternative to catch ConversionException?" is NO

JSON - Convert Object to JSON Array

i try to convert a class object which are generated via Reflection and convert them to JSON string. following is my methods
public Object creatObjectAsString(String className) {
Object objects = null;
try {
objects = java.lang.reflect.Array.newInstance( Class.forName(className), 1);
//System.out.println(objects.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return objects ;
}
public String convertPlainObjectToJSON( Object obj,boolean isArray){
String jsonString="",tempJSON="";
JSONSerializer serializer = new JSONSerializer();
tempJSON = serializer.serialize(obj);
if(isArray){
jsonString="["+tempJSON+"]";
}else{
jsonString=tempJSON;
}
return jsonString;
}
I have hard coded the following lines since i did not know how to create JSON Array which is not the correct way of programming.
if(isArray){
jsonString="["+tempJSON+"]";
}else{
jsonString=tempJSON;
}
when i printed the convertPlainObjectToJSON result of method i get the following [[null]] which is not expected.
what is the mistake i make.
Please correct me.
If you notice your output, you can see [[ (double square braces), which means the JSONSerializer has already converted it to an JSONArray. Therefore, you needn't do it again manually.
And regarding the null between them, it is because you're passing null to the convertPlainObjectToJSON. Send a newly created object array (as #MvG mentioned), new Object[0], and you'll get what you want!
Always remember that blank and null are not the same!

how to convert a string to float and avoid using try/catch in java?

There are some situation that I need to convert string to float or some other numerical data-type but there is a probability of getting some nonconvertible values such as "-" or "/" and I can't verify all the values beforehand to remove them.
and I want to avoid using try/catch for this matter , is there any other way of doing a proper conversion in java? something similar to C# TryParse?
The simplest thing I can think of is java.util.Scanner . However this approach requires a new Scanner instance for each String.
String data = ...;
Scanner n = new Scanner(data);
if(n.hasNextInt()){//check if the next chars are integer
int i = n.nextInt();
}else{
}
Next you could write a regex pattern that you use to check the String (complex to fail too big values) and then call Integer.parseInt() after checking the string against it.
Pattern p = Pattern.compile("insert regex to test string here");
String data = ...;
Matcher m = p.matcher(data);
//warning depending on regex used this may
//only check part of the string
if(m.matches()){
int i = Integer.parseInt(data);
}
However both of these parse the string twice, once to test the string and a second time to get the value. Depending on how often you get invalid strings catching an exception may be faster.
Unfortunately, there is no such method in Java. There is no out parameter in Java, so writing such a method would need to return a null Float to signal an error, or to pass a FloatHolder object which could be modified by the method:
public class FloatHolder {
private float value;
public void setValue(float value) {
this.value = value;
}
public float getValue() {
return this.value;
}
}
public static boolean tryParseFloat(String s, FloatHolder holder) {
try {
float value = Float.parseFloat(s);
holder.setValue(value);
}
catch (NumberFormatException e) {
return false;
}
}
This is an old question, but since all the answers fail to mention this (and I wasn't aware of it myself until seeing it in a merge request written by a colleague), I want to point potential readers to the Guava Floats and Ints classes:
With the help of these classes, you can write code like this:
Integer i = Ints.tryParse("10");
Integer j = Ints.tryParse("invalid");
Float f = Floats.tryParse("10.1");
Float g = Floats.tryParse("invalid.value");
The result will be null if the value is an invalid int or float, and you can then handle it in any way you like. (Be careful to not just cast it to an int/float, since this will trigger a NullPointerException if the value is an invalid integer/floating point value.)
Note that these methods are marked as "beta", but they are quite useful anyway and we use them in production.
For reference, here are the Javadocs for these classes:
https://google.github.io/guava/releases/snapshot-jre/api/docs/com/google/common/primitives/Ints.html
https://google.github.io/guava/releases/snapshot-jre/api/docs/com/google/common/primitives/Floats.html
Java does not provide some built in tryParse type of methods, on of the solutions you can try is to create your own tryParse Method and put try/catch code in this method and then you can easily use this method across your application very easily and without using try/catch at all the places you use the method.
One of the sample functions can have following code
public static Long parseLong(String value) {
if(isNullOrEmpty(value)) {
return null;
}
try {
return Long.valueOf(value);
}
catch (NumberFormatException e) {
}
return null;
}
Regular expressions helped me solve this issue. Here is how:
Get the string input.
Use the expression that matches one or more digits.
Parse if it is a match.
String s = "1111";
int i = s.matches("^[0-9]+$") ? Integer.parseInt(s) : -1;
if(i != -1)
System.out.println("Integer");
else
System.out.println("Not an integer");

sort doubles stored as strings ?

Hi is there any way to parse strings into numbers? And is there any way to check if a string is a number or not without breaking the program ? I am thinking about using a try and catch would this be a good idea ?
There's no way to check if a string is parseable or not without trying to parse the string (as any check would have to start trying to interpret the string as a number to do that...). For a half-way check, I guess you could use Regex to check if the string has only digits and periods. You'll have to use a try... catch block aswell, though.
As to how to parse a string into a double, try this:
double dd;
try {
dd = Double.parseDouble(string);
}
catch (NumberFormatException e) {
System.out.println("couldnt not parse the string!");
}
Yes. Double.valueOf(String s) will throw a NumberFormatException if your string can't be parsed to a Double and return the parsed Double otherwise.
I'm assuming you want to sort using one of the assorted built-in sort methods. In that case, you'll need to create a custom Comparator<T>, implementing compare() and equals() that attempts to parse the strings as Double, and on catching an exception, implements some sane default behavior. Make sure to catch the exception within your methods - you should only run into problems if you let the exceptions get out into the Java API code.
As a quick example to get you going:
class DoubleStringComparator implements Comparator<String> {
public int compare(String o1, String o2) {
try {
double d1 = Double.parse(o1);
double d2 = Double.parse(d2);
if d1 > d2 {
return 1;
} else if d1 < d2 {
return -1;
else {
return 0;
}
} catch (NumberFormatException e) {
// whatever ordering you want to impose when one string is not a double
}
}
// some definition of equals() - whatever makes sense for your application
}
Then, when you want to do the sorting:
Collections.sort(someListOfString, new DoubleStringComparator());
Take a look at parseDouble
http://download.oracle.com/javase/6/docs/api/java/lang/Double.html#parseDouble%28java.lang.String%29
and yes you can catch NumberFormatException to determine when the number wasn't valid.
You can use regex to find if the strings is double or not
if(num1.matches(("((-|\\+)?[0-9]+(\\.[0-9]+)?)+"))){
isDoubleVal =true;
}else{
isDoubleVal = false;
}
Hope it helps you.
Regards,
Lav

Categories