NumberFormatException в GSON при преобразовании строки в двойное число - PullRequest
5 голосов
/ 11 февраля 2012

Я работаю с JSON-ответом, который неправильно отформатирован. Все поля возвращаются как Strings. К сожалению, У меня нет контроля над возвращаемыми данными .

Я использую Gson и пытаюсь проанализировать объект JSON, который включает в себя поле, подобное следующему:

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

Очевидно, он должен быть напечатан как Number. Когда я пытаюсь разобрать это как String, Number или double, я получаю 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);

Итак, я последовал за этим похожим вопросом и попытался создать 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(), по крайней мере?

Любая помощь / руководство очень ценится.

Ответы [ 5 ]

9 голосов
/ 01 ноября 2013

Вы также можете использовать GsonBuilder registerTypeAdapter() для перехвата возможных исключений при разборе и обработки их так, как вы хотите.

Пример для перехвата NumberFormatException при разборе Float и получения значения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);
        }

    });
2 голосов
/ 11 февраля 2012

Мне пришлось написать JsonDeserializer для всего моего класса «Item».

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

Все равно хотелось бы увидеть решение для моей первоначальной проблемы, поэтому мне не пришлось бы вручную анализировать каждое поле.

0 голосов
/ 11 июня 2018

Я тоже столкнулся с подобной ситуацией. Я использовал ниже адаптер для преобразования. Я нашел это кратким.

.registerTypeAdapter(Double.class, new JsonSerializer<Double>() {
            public JsonElement serialize(Double number, Type type, JsonSerializationContext context) {
                return new JsonPrimitive(Double.valueOf(number));
            }
        })
0 голосов
/ 14 ноября 2013

Пол, у меня похожая проблема получения чисел в моем 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, я преобразовал в enum, поскольку у меня были дискретные данные.

0 голосов
/ 27 февраля 2012

Похоже, что поле cost в вашем классе Item объявлено как int, а не как double. Изменение стоимости на double должно исправить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...