Retrofit提交Raw JSON报错,伴生Place接口无法实例化异常求助
嘿,我来帮你搞定这个Retrofit的坑!
首先,咱们先揪出问题的根源:你遇到的java.lang.UnsupportedOperationException: Interface can't be instantiated! Interface name: com.google.android.gms.location.places.Place异常,本质是你的请求Model(或者CookDetails类)里用到了Place这个Google提供的接口作为字段。
Postman能正常跑是因为它直接发Raw JSON字符串,不需要处理Java对象的实例化;但Retrofit用Gson做序列化时,会尝试把你的Java对象转成JSON,而接口是不能被直接new出来的,Gson不知道怎么实例化这个Place接口,自然就报错了。
给你几个针对性的解决方案,按优先级排序:
1. 最省心:把接口换成自定义POJO类
既然你只需要把Place的相关数据传给后端,完全没必要用Google的Place接口,自己写一个包含所需字段的实体类就行:
// 自定义的Place实体类,只保留你需要传给后端的字段 public class MyPlace { private String placeId; private String name; private String address; // 其他你要传的字段,比如latitude、longitude // 别忘了加无参构造、getter/setter,或者用Lombok简化 }
然后把你原来Model类里的Place字段换成MyPlace:
public class YourRequestModel { private MyPlace place; // 其他原有字段... }
这样Gson就能正常序列化这个实体类,不会再报错。
2. 自定义Gson TypeAdapter(如果必须用Place接口)
如果你因为某些原因一定要保留Place接口,可以给Gson写一个自定义的适配器,告诉它怎么序列化/反序列化Place对象:
public class PlaceTypeAdapter extends TypeAdapter<Place> { @Override public void write(JsonWriter out, Place value) throws IOException { // 把Place接口里的字段写入JSON,按后端需要的格式来 out.beginObject(); out.name("placeId").value(value.getId()); out.name("name").value(value.getName()); out.name("address").value(value.getAddress()); // 按需添加其他字段 out.endObject(); } @Override public Place read(JsonReader in) throws IOException { // 如果你的接口需要接收后端返回的Place数据,这里要实现反序列化逻辑 // 用Google提供的Place.Builder来创建实例 in.beginObject(); String placeId = null; CharSequence name = null; CharSequence address = null; while (in.hasNext()) { switch (in.nextName()) { case "placeId": placeId = in.nextString(); break; case "name": name = in.nextString(); break; case "address": address = in.nextString(); break; } } in.endObject(); return new Place.Builder() .setId(placeId) .setName(name) .setAddress(address) .build(); } }
然后在Retrofit的Gson配置里注册这个适配器:
Gson customGson = new GsonBuilder() .registerTypeAdapter(Place.class, new PlaceTypeAdapter()) .create(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(YOUR_BASE_URL) .addConverterFactory(GsonConverterFactory.create(customGson)) .build();
3. 检查CookDetails类
别忘了排查你的CookDetails类,确保里面也没有用类似的接口类型作为字段,所有参与序列化的字段都必须是可实例化的类(不是接口、抽象类)。
按上面的方法调整后,Retrofit应该就能正常发送请求啦!
内容的提问来源于stack exchange,提问作者Gulfam Khan

