【问题标题】:Retrofit2 accessing an internal array of objectsRetrofit2 访问内部对象数组
【发布时间】:2021-04-08 13:40:06
【问题描述】:

我正在尝试从 Json 文件中提取对象列表,但是该文件以一个对象开头,该对象包含我需要的对象数组。我是新来改造这里是我的文件: 接口

public interface OSMApi {

    @Headers({"Accept: application/json"})
    @GET("map")
    Call<List<OSMObject>> getOSMObjects(@Query("bbox") String boxMinMaxLatLon);
}

控制器

public class OSMController implements Callback<List<OSMObject>> {

    static final String BASE_URL = "https://api.openstreetmap.org/api/0.6/";
    private static final String TAG = "OSMController";

    private String bboxLatLon = "//latlongshere";

    public void start(){
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build();

    OSMApi osmApi = retrofit.create(OSMApi.class);

    Call<List<OSMObject>> call = osmApi.getOSMNodes(bboxLatLon);
    call.enqueue(this);
}

    @Override
    public void onResponse(Call<List<OSMObject>> call, Response<List<OSMObject>> response) {
        if(response.isSuccessful()){
            List<OSMObject> OSMObjectList = response.body();
            OSMObjectList.forEach(OSMObject -> Log.d(TAG, "onResponse: objects "+OSMObject.getId()));
        }else{
            Log.d(TAG, "onResponse: here : "+response.errorBody() + ", "+response.code());
        }
    }

    @Override
    public void onFailure(Call<List<OSMObject>> call, Throwable t) {
        Log.d(TAG, "onFailure: "+ t.getStackTrace() + ", extra: "+ t.getMessage());
    }
}

Json 的开头

{
    "version": "0.6",
    "generator": "CGImap 0.8.3 (652902 spike-07.openstreetmap.org)",
    "copyright": "OpenStreetMap and contributors",
    "attribution": "http://www.openstreetmap.org/copyright",
    "license": "http://opendatacommons.org/licenses/odbl/1-0/",
    "bounds": {
        "minlat": 1.0,
        "minlon": 1.0,
        "maxlat": 1.0,
        "maxlon": 1.0
    },
    "elements": [
        {
            "type": "node",
            "id": 443479273,
            "lat": 1.0,
            "lon": 1.0,
            "timestamp": "2011-04-11T18:06:02Z",
            "version": 3,
            "changeset": 4435725,
            "user": "BeerOfTheTrip",
            "uid": 440880
        },
        {
            "type": "node",
            "id": 443479278,
            "lat": 1.0,
            "lon": 1.0,
            "timestamp": "2011-04-11T18:06:01Z",
            "version": 2,
            "changeset": 4435725,
            "user": "BeerOfTheTrip",
            "uid": 440880
        },
        {
            "type": "node",
            "id": 443479281,
            "lat": 1.0,
            "lon": 1.0,
            "timestamp": "2011-04-11T18:06:01Z",
            "version": 2,
            "changeset": 4435725,
            "user": "BeerOfTheTrip",
            "uid": 440880
        },
etc..........

我的对象Pojo

public class OSMObject implements SerializedName {

    @SerializedName("type")
    @Expose
    private String type;
    @SerializedName("id")
    @Expose
    private int id;
    @SerializedName("lat")
    @Expose
    private double lat;
    @SerializedName("lon")
    @Expose
    private double lon;
    @SerializedName("timestamp")
    @Expose
    private String timestamp;
    @SerializedName("version")
    @Expose
    private int version;
    @SerializedName("changeset")
    @Expose
    private int changeset;
    @SerializedName("uid")
    @Expose
    private int uid;
    @SerializedName("nodes")
    @Expose
    private int[] nodes;

    //Separation
    private ArrayList<OSMNode> OSMNodes = new ArrayList<>();
    private ArrayList<OSMWay> OSMWays = new ArrayList<>();

    public OSMObject(String type, int id, String timestamp, int version, int changeset, int uid, int[] nodes) {
        this.type = type;
        this.id = id;
        this.timestamp = timestamp;
        this.version = version;
        this.changeset = changeset;
        this.uid = uid;
        this.nodes = nodes;
    }

    public OSMObject(String type, int id, double lat, double lon, String timestamp, int version, int changeset, int uid) {
        this.type = type;
        this.id = id;
        this.lat = lat;
        this.lon = lon;
        this.timestamp = timestamp;
        this.version = version;
        this.changeset = changeset;
        this.uid = uid;
    }

+getters and setters....

所以我不需要 jsonObject 中的任何初始信息,我只需要 Elements jsonArray 中的对象列表,这由两个略有不同的对象组成,一个有 Nodes[] 一个没有。因此 pojo 中的 2 个构造函数?

如何设置改造来处理这个问题?目前我遇到的错误是:

onFailure: [Ljava.lang.StackTraceElement;@dbe860f, extra: 预期 BEGIN_ARRAY 但在第 1 行第 2 列路径 $ 处是 BEGIN_OBJECT

补充: 两个不同对象的示例:

        {
            "type": "node",
            "id": 4448646916,
            "lat": 1.0,
            "lon": 1.0,
            "timestamp": "2020-12-21T17:52:35Z",
            "version": 1,
            "changeset": 44211151,
            "user": "Mike Greenwood",
            "uid": 44623152
        },
        {
            "type": "way",
            "id": 44117969,
            "timestamp": "2014-04-11T14:01:16Z",
            "version": 2,
            "changeset": 44627679,
            "user": "Smurfy12",
            "uid": 44220096,
            "nodes": [
                4483345702,
                443479293,
                443479273
            ],
            "tags": {
                "highway": "residential",
                "name": "A Street"
            }
        },

正如您所看到的,它们具有不同的“类型”,一个“节点”和一个“方式”,方式有一个节点数组,而节点有一个“纬度”和“经度”,我不需要担心现在的“标签”。

【问题讨论】:

    标签: java android retrofit2


    【解决方案1】:

    在“onResponse”中,试试这个:

        if (response.isSuccessful()) {
    
            JSONObject reader = new JSONObject(response.body());
    
            List<OSMObject> OSMObjectList = (List<OSMObject>) reader.getJSONArray("elements");
    
            // now you can work on your "elements" list..
    
        } else {
            Log.d(TAG, "onResponse: here : " + response.errorBody() + ", " + response.code());
        }
    

    关于 2 个构造函数的注意事项 - 我不确定你如何区分你需要使用哪个构造函数,因为在你的“元素”数组中只有 3 个类似的对象,所以如果你需要帮助 - 请解释您可能在该数组中收到的另一个对象的区别或展示示例。

    编辑: 您可以添加新课程并使用它来回复您的回复:

    public class JsonResponse {
    
        private ArrayList<OSMObject> elements;
    
        public ArrayList<OSMObject> getElements() {
            return elements;
        }
    }
    

    在您的 ApiInterface 更改以期望得到回报:

    Call<JsonResponse> login...
    

    然后,当您拨打电话时,您可以使用以下方式获取列表:

    List<OSMObject> OSMObjectList = response.body().getElements();
    

    所以现在您可以在操作数据之前或之后保存。

    【讨论】:

    • 我可以看到您在处理数组方面的目标,但是我的示例中的响应正文期望 List 如何在整个示例中更改它以仅返回 JSONObject然后我可以操纵吗?感谢您的帮助。
    • 感谢您的说明,我已对元素数组中的两个对象添加了一些说明。谢谢。
    • 我明白了,我已经编辑了我的答案 - 您可以添加我提到的额外类“JsonResponse”并以这种方式获取您的元素数据。希望这会有所帮助
    【解决方案2】:

    解决方案

    请像这样更改你的 pojo 类

    
    @Generated("jsonschema2pojo")
    public class OSMObject implements Serializable
    {
    
    @SerializedName("version")
    @Expose
    private String version;
    @SerializedName("generator")
    @Expose
    private String generator;
    @SerializedName("copyright")
    @Expose
    private String copyright;
    @SerializedName("attribution")
    @Expose
    private String attribution;
    @SerializedName("license")
    @Expose
    private String license;
    @SerializedName("bounds")
    @Expose
    private Bounds bounds;
    @SerializedName("elements")
    @Expose
    private List<Element> elements = null;
    private final static long serialVersionUID = -4976252003298473695L;
    
    public String getVersion() {
    return version;
    }
    
    public void setVersion(String version) {
    this.version = version;
    }
    
    public String getGenerator() {
    return generator;
    }
    
    public void setGenerator(String generator) {
    this.generator = generator;
    }
    
    public String getCopyright() {
    return copyright;
    }
    
    public void setCopyright(String copyright) {
    this.copyright = copyright;
    }
    
    public String getAttribution() {
    return attribution;
    }
    
    public void setAttribution(String attribution) {
    this.attribution = attribution;
    }
    
    public String getLicense() {
    return license;
    }
    
    public void setLicense(String license) {
    this.license = license;
    }
    
    public Bounds getBounds() {
    return bounds;
    }
    
    public void setBounds(Bounds bounds) {
    this.bounds = bounds;
    }
    
    public List<Element> getElements() {
    return elements;
    }
    
    public void setElements(List<Element> elements) {
    this.elements = elements;
    }
    }
    
    
    @Generated("jsonschema2pojo")
    public class Bounds implements Serializable
    {
    
    @SerializedName("minlat")
    @Expose
    private Float minlat;
    @SerializedName("minlon")
    @Expose
    private Float minlon;
    @SerializedName("maxlat")
    @Expose
    private Float maxlat;
    @SerializedName("maxlon")
    @Expose
    private Float maxlon;
    private final static long serialVersionUID = -8105102004947849058L;
    
    public Float getMinlat() {
    return minlat;
    }
    
    public void setMinlat(Float minlat) {
    this.minlat = minlat;
    }
    
    public Float getMinlon() {
    return minlon;
    }
    
    public void setMinlon(Float minlon) {
    this.minlon = minlon;
    }
    
    public Float getMaxlat() {
    return maxlat;
    }
    
    public void setMaxlat(Float maxlat) {
    this.maxlat = maxlat;
    }
    
    public Float getMaxlon() {
    return maxlon;
    }
    
    public void setMaxlon(Float maxlon) {
    this.maxlon = maxlon;
    }
    }
    
    
    
    @Generated("jsonschema2pojo")
    public class Element implements Serializable
    {
    
    @SerializedName("type")
    @Expose
    private String type;
    @SerializedName("id")
    @Expose
    private Integer id;
    @SerializedName("lat")
    @Expose
    private Float lat;
    @SerializedName("lon")
    @Expose
    private Float lon;
    @SerializedName("timestamp")
    @Expose
    private String timestamp;
    @SerializedName("version")
    @Expose
    private Integer version;
    @SerializedName("changeset")
    @Expose
    private Integer changeset;
    @SerializedName("user")
    @Expose
    private String user;
    @SerializedName("uid")
    @Expose
    private Integer uid;
    private final static long serialVersionUID = 8944398333022644493L;
    
    public String getType() {
    return type;
    }
    
    public void setType(String type) {
    this.type = type;
    }
    
    public Integer getId() {
    return id;
    }
    
    public void setId(Integer id) {
    this.id = id;
    }
    
    public Float getLat() {
    return lat;
    }
    
    public void setLat(Float lat) {
    this.lat = lat;
    }
    
    public Float getLon() {
    return lon;
    }
    
    public void setLon(Float lon) {
    this.lon = lon;
    }
    
    public String getTimestamp() {
    return timestamp;
    }
    
    public void setTimestamp(String timestamp) {
    this.timestamp = timestamp;
    }
    
    public Integer getVersion() {
    return version;
    }
    
    public void setVersion(Integer version) {
    this.version = version;
    }
    
    public Integer getChangeset() {
    return changeset;
    }
    
    public void setChangeset(Integer changeset) {
    this.changeset = changeset;
    }
    
    public String getUser() {
    return user;
    }
    
    public void setUser(String user) {
    this.user = user;
    }
    
    public Integer getUid() {
    return uid;
    }
    
    public void setUid(Integer uid) {
    this.uid = uid;
    }
    }
    

    之后

    你已经从 onResponse 方法中得到了 Arrayist

    @Override
        public void onResponse(Call<List<OSMObject>> call, Response<List<OSMObject>> response) {
            if(response.isSuccessful()){
                List<OSMObject> OSMObjectList = response.body().getElements();
               Log.d(TAG, "onResponse: here : "+response.body().getElements());
            }else{
                Log.d(TAG, "onResponse: here : "+response.errorBody() + ", "+response.code());
            }
        }
    
        @Override
        public void onFailure(Call<List<OSMObject>> call, Throwable t) {
            Log.d(TAG, "onFailure: "+ t.getStackTrace() + ", extra: "+ t.getMessage());
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-23
      • 2021-08-25
      • 2015-05-04
      • 2015-03-20
      • 2021-02-28
      • 2017-02-05
      相关资源
      最近更新 更多