I am working with a JSON response that is improperly formatted. All fields are being returned as Strings
. Unfortunately, I have no control over the return data.
I am using Gson and attempting to parse a JSON object that includes a field like this:
{
[...]
"cost": "9.25"
}
It should obviously be printed as a Number
. When I try to parse this as a String
, Number
or double
I get a NumberFormatException:
com.google.gson.JsonSyntaxException: java.lang.NumberFormatException:
[...]
at com.myapp.android.LauncherActivity$1.onSuccess(LauncherActivity.java:69)
[...]
Caused by: java.lang.NumberFormatException:
at org.apache.harmony.luni.util.FloatingPointParser.parseDouble(FloatingPointParser.java:267)
at java.lang.Double.parseDouble(Double.java:285)
at com.google.gson.stream.JsonReader.nextInt(JsonReader.java:599)
at com.google.gson.internal.bind.TypeAdapters$7.read(TypeAdapters.java:228)
... 19 more
LauncherActivity Line 69:
Item item = gson.fromJson(response, Item.class);
So I followed this similar question and tried creating a TypeAdapter
like so:
public class CostTypeAdapter implements JsonDeserializer<Double>, JsonSerializer<Double> {
public Double deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Double cost;
try {
cost = json.getAsDouble();
} catch (NumberFormatException e) {
cost = 0.00d;
}
return cost;
}
public JsonElement serialize(Double src, Type typeOfSrc,
JsonSerializationContext context) {
return new JsonPrimitive(src);
}
}
And registered it when creating the GsonBuilder
:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Cost.class, new CostTypeAdapter());
Gson gson = builder.create();
And my Cost
class:
public class Cost {
private Double value;
public Cost(Double value) {
this.value = value;
}
public Double getValue() {
return value;
}
}
But I get the same NumberFormatException
.
Any ideas on whats happening here? Shouldn't this exception be caught in my CostTypeAdapter.deserialize()
, at the very least?
Any help/guidance is greatly appreciated.
You can also use GsonBuilder
's registerTypeAdapter()
to catch possible parsing Exceptions and deal with them the way you want.
Example for catching NumberFormatException
when parsing Float
and make the value null:
GsonBuilder gb = new GsonBuilder();
gb.registerTypeAdapter(Float.class, new TypeAdapter<Float>() {
@Override
public Float read(JsonReader reader) throws IOException {
if (reader.peek() == JsonToken.NULL) {
reader.nextNull();
return null;
}
String stringValue = reader.nextString();
try {
Float value = Float.valueOf(stringValue);
return value;
} catch (NumberFormatException e) {
return null;
}
}
@Override
public void write(JsonWriter writer, Float value) throws IOException {
if (value == null) {
writer.nullValue();
return;
}
writer.value(value);
}
});
I ended up having to write a JsonDeserializer
for my entire enclosing "Item" class.
public class ItemDeserializer implements JsonDeserializer<Item> {
@Override
public Item deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
JsonObject jobject = (JsonObject) json;
return new Item(
[...],
(jobject.has("cost")) ? jobject.get("cost").getAsDouble() : 0.00d
);
}
}
Would still love to see a solution for my original issue, so I wouldn't have to manually parse every field.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With