2012-02-11 3 views
3

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

Я использую 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 Линия 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(), по крайней мере?

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

ответ

2

В конце концов мне пришлось написать 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 
       ); 
    } 
} 

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

+3

хотите, чтобы это было разрешено с помощью аннотации какого-то типа – Gubatron

0

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

7

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

Пример для ловли NumberFormatException при разборе Float и сделать нулевое значение:

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

    }); 
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, я преобразовал в перечисление, так как я имел дискретные данные.

Смежные вопросы