我正在使用格式不正确的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第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()
至少应该抓住这个例外吗?
非常感谢任何帮助/指导。
答案 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);
}
}