Какой тип данных использовать для парсинга запросов Retrofit?
У меня есть сайт, с которого я с помощью retrofit делаю парсинг данных. С помощью конвертера я получил класс, который соответствует структуре данных одной песни. Когда пытаюсь использовать List, то он пишет:
/System.err: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 3 path $[0].
Код:
MainActivity:
public class MainActivity extends AppCompatActivity {
EditText input;
Link link;
String url = "https://api.xn--41a.ws/";
Retrofit retrofit;
TextView txt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt = findViewById(R.id.text);
retrofit = new Retrofit.Builder().baseUrl(url).addConverterFactory(GsonConverterFactory.create()).build();
link = retrofit.create(Link.class);
link.getSongs("Sting").enqueue(new Callback<List<GetSong>>() {
@Override
public void onResponse(Call<List<GetSong>> call, Response<List<GetSong>> response) {
txt.setText("good");
}
@Override
public void onFailure(Call<List<GetSong>> call, Throwable t) {
txt.setText("Fail");
t.printStackTrace();
}
});
}
}
GetSong.java:
public class GetSong {
@SerializedName("audio_id")
@Expose
private String audioId;
@SerializedName("artist")
@Expose
private String artist;
@SerializedName("title")
@Expose
private String title;
@SerializedName("mp3")
@Expose
private String mp3;
@SerializedName("duration")
@Expose
private Integer duration;
@SerializedName("img")
@Expose
private String img;
@SerializedName("hash")
@Expose
private String hash;
public String getAudioId() {
return audioId;
}
public void setAudioId(String audioId) {
this.audioId = audioId;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getMp3() {
return mp3;
}
public void setMp3(String mp3) {
this.mp3 = mp3;
}
public Integer getDuration() {
return duration;
}
public void setDuration(Integer duration) {
this.duration = duration;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
}
Link.java:
public interface Link {
@GET("api.php?method=search&key=5d2ef46e867e57510c93238c8bd5708a&v=3")
Call<List<GetSong>> getSongs(@Query("q") String text);
}
Ответы (1 шт):
Учитывая мой последний комментарий, вот вам ответ на вопрос. Кастомный десериализатор никто не отменял (писать его вам придется самостоятельно), я предоставлю вам ссылку на пример такого решения, однако, данный код тоже будет работать (хотя и не без костылей), при этом надеюсь он объяснит вам суть проблемы. Вот ссылка, почитайте, как правильно решаются такие проблемы: https://stackoverflow.com/questions/45639018/java-parse-json-with-array-with-different-object-types-gson-or-jackson-or-etc И, разумеется,код:
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class Test {
private static String url = "https://api.xn--41a.ws/";
private final static Type TYPE = new TypeToken<List<GetSong>>(){}.getType();
private final static Gson GSON = new Gson();
public static void main(String[] args) throws IOException {
Link link = new Retrofit.Builder().baseUrl(url).addConverterFactory(GsonConverterFactory.create()).build().create(Link.class);
Object obj = link.getSongs("").execute().body().get(0);
List<GetSong> result = GSON.fromJson(GSON.toJson(obj), TYPE);
System.out.println(result);
}
}
import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface Link {
@GET("api.php?method=search&key=5d2ef46e867e57510c93238c8bd5708a&v=3")
Call<List> getSongs(@Query("q") String text);
}