将String转换为double时GSON中的NumberFormatException

时间:2012-02-11 09:24:24

标签: java android json gson

我正在使用格式不正确的JSON响应。所有字段都以Strings的形式返回。不幸的是,我无法控制返回数据

我正在使用Gson并尝试解析包含如下字段的JSON对象:

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

显然应该打印为Number。当我尝试将其解析为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第69行:

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

所以我跟着this similar question尝试创建一个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);
    }
}

在创建GsonBuilder时注册了它:

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

我的Cost课程:

public class Cost {
    private Double value;

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

    public Double getValue() {
        return value;
    }
}

但我得到同样的NumberFormatException

关于这里发生的任何想法?我的CostTypeAdapter.deserialize()至少应该抓住这个例外吗?

非常感谢任何帮助/指导。

6 个答案:

答案 0 :(得分:9)

您还可以使用GsonBuilder的{​​{1}}来捕获可能的解析异常并按照您希望的方式处理它们。

解析registerTypeAdapter()时捕获NumberFormatException并使值为null的示例:

Float

答案 1 :(得分:2)

我最后不得不为我整个封闭的“Item”类写一个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
                );
    }
}

仍然希望看到原始问题的解决方案,因此我不必手动解析每个字段。

答案 2 :(得分:0)

看起来,您的Item类中的cost字段被声明为int,而不是double。将费用更改为double应该可以解决问题。

答案 3 :(得分:0)

保罗,我有一个类似的问题,即在我的JSON中获取存储为String的数字。对我有用的是:

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());
    }
}

好像你的案例中有连续的数据,所以你只需要class就可以了,因为我有离散数据,所以我转换为枚举。

答案 4 :(得分:0)

我也遇到了类似的情况。我使用下面的适配器进行转换。我发现它很简洁。

@Singleton
class BomberManController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {

  def index() = Action { implicit request: Request[AnyContent] =>
    Ok("test")
  }
}

答案 5 :(得分:0)

最简单的解决方案是将属性设置为String而不是double,并在get方法中将其解析为double。

例如:

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);
    }
}