简体   繁体   English

将 String 转换为 double 时 GSON 中的 NumberFormatException

[英]NumberFormatException in GSON when converting String to double

I am working with a JSON response that is improperly formatted.我正在处理格式不正确的 JSON 响应。 All fields are being returned as Strings .所有字段都作为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:我正在使用 Gson 并尝试解析包含如下字段的 JSON 对象:

{
        [...]
    "cost": "9.25"
}

It should obviously be printed as a Number .它显然应该打印为Number When I try to parse this as a String , Number or double I get a NumberFormatException:当我尝试将其解析为StringNumberdouble我得到一个 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: LauncherActivity 第 69 行:

Item item = gson.fromJson(response, Item.class);

So I followed this similar question and tried creating a TypeAdapter like so:所以我跟着这个类似的问题,并尝试创建一个TypeAdapter像这样:

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时注册它:

GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Cost.class, new CostTypeAdapter());
Gson gson = builder.create(); 

And my Cost class:还有我的Cost课程:

public class Cost {
    private Double value;

    public Cost(Double value) {
        this.value = value;
    }

    public Double getValue() {
        return value;
    }
}

But I get the same NumberFormatException .但我得到了相同的NumberFormatException

Any ideas on whats happening here?关于这里发生了什么的任何想法? Shouldn't this exception be caught in my CostTypeAdapter.deserialize() , at the very least?至少在我的CostTypeAdapter.deserialize()不应该捕获这个异常吗?

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.您还可以使用GsonBuilderregisterTypeAdapter()来捕获可能的解析异常并以您想要的方式处理它们。

Example for catching NumberFormatException when parsing Float and make the value null:解析Float时捕获NumberFormatException并将值设为 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.我最终JsonDeserializer为我整个封闭的“项目”类编写一个JsonDeserializer

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.仍然希望看到我原来问题的解决方案,所以我不必手动解析每个字段。

Paul, I have a similar issue of getting numbers in my JSON that are stored as String s.保罗,我有一个类似的问题,即在我的 JSON 中获取存储为String的数字。 What's been working for me is this:对我有用的是:

public enum Plan {
        GUEST_PASS, FREE, PREMIUM;

        static Plan fromValue(int value) {
            for (Plan plan : plans)
                if (value == plan.ordinal())
                    return plan;
            throw new IllegalArgumentException("Invalid value for Plan: " + value);
        }

        static Plan fromValue(String string) {
            try {
                return fromValue(parseInt(string));
            } catch (IllegalArgumentException _) {
                throw new IllegalArgumentException("Invalid value for Plan: " + string);
            }
        }

        private static EnumSet<Plan> plans = EnumSet.allOf(Plan.class);
    }

public static class PlanAdapter extends TypeAdapter<Plan> {
    @Override public void write(JsonWriter json, Plan plan) throws IOException {
        json.value(Integer.toString(plan.ordinal()));
    }

    @Override public Plan read(JsonReader json) throws IOException {
        return Plan.fromValue(json.nextString());
    }
}

Seems like you have continuous data in your case, so you would suffice to have a class , I converted to an enum since I had discrete data.好像你的案例中有连续数据,所以你有一个class就足够了,因为我有离散数据,所以我转换为 enum 。

I also ran into a similar situation.我也遇到过类似的情况。 I used below adaptor for the conversion.我使用以下适配器进行转换。 I Found it concise.我发现它很简洁。

.registerTypeAdapter(Double.class, new JsonSerializer<Double>() {
            public JsonElement serialize(Double number, Type type, JsonSerializationContext context) {
                return new JsonPrimitive(Double.valueOf(number));
            }
        })

the easiest solution is to make the attribute to be String instead of double and in the get method parse it to double.最简单的解决方案是将属性设为 String 而不是 double 并在 get 方法中将其解析为 double。

for example:例如:

class Location {
 private String latitude;
 private String longitude;

 public double getLatitude() {
        return latitude.isEmpty() ? 0d : Double.parseDouble(latitude);
    }

    public double getLongitude() {
        return longitude.isEmpty() ? 0d : Double.parseDouble(longitude);
    }
}

It looks like the cost field in your Item class is declared as an int , not as a double .看起来 Item 类中的cost字段被声明为int ,而不是double Changing cost to a double should fix it.将成本更改为double应该可以解决此问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM