How to get "description" from GET method in retrofit android with Fragment or xml and Retrofit interface and retrofit client ,full code actually i've face some issues.
I'm trying some time but i can't fix this API.
JSON response.
{
"statuscode": 200,
"status": "true",
"cmsDetails": {
"id": 2,
"title": "Privacy Policy",
"description": "<p>We, Devoid Technologies Pvt. Ltd., incorporated."
}
}
Retrofit Interface
#GET("retrieve/policy")
Call<CMSDetails> getDescription();
I want get Description in cmsDetails object.
Create a model for the JSON Response like this :
public class CMS
{
#SerializedName("statuscode")
private String statuscode;
#SerializedName("status")
private String status;
#SerializedName("cmsDetails")
private CmsDetails cmsDetails;
public CmsDetails getCmsDetails()
{
return cmsDetails;
}
}
Now create another model for CmsDetails:
public class CmsDetails
{
#SerializedName("id")
private int id;
#SerializedName("title")
private String title;
#SerializedName("description")
private String description;
public String getDescription()
{
return description;
}
}
Now create your endpoint like this:
public interface EndPoints {
#GET("retrieve/policy")
Call<CMS> getDescriptionCms();
}
Now create the client as follows :
public class RetroFitCMSClient {
private static Retrofit retrofit;
private static OkHttpClient okClient;
private static final String BASE_URL = "http://test.test;
public static Retrofit getRetrofitInstance() {
okClient = new OkHttpClient
.Builder()
.build();
if (retrofit == null) {
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
Now you can make your call retrofit call and get the description like this :
EndPoints service = RetroFitCMSClient.getRetrofitInstance().create(EndPoints.class);
call = service.getDescriptionCms();
call.enqueue(new Callback<CMS>() {
#Override
public void onResponse(Call<CMS> call, Response<CMS> response) {
if(response.isSuccessful()) {
String description = response.body().getCmsDetails().getDescription();
}
}
#Override
public void onFailure(Call<CMS> call, Throwable throwable) {
}
}
Related
New to Spring, so I want to return either a 400 or a 201 (Created) with a REST endpoint, but right now it only returns an empty 200 response via Postman.
SampleService.java
#Service
public class SampleService {
private SampleRepository sampleRepository;
#Autowired
public SampleService(SampleRepository sampleRepository) {
this.sampleRepository = sampleRepository;
}
public ResponseEntity<Response> registerData(Data data) {
Optional<SampleData> dataOptional = sampleRepository.findDataByName(data.getName());
if(dataOptional.isPresent()) {
// Returns blank 200 response
return new ResponseEntity<>(
new Error(
"Bad Request",
"Data already exists."
),
HttpStatus.BAD_REQUEST
);
}
sampleRepository.save(data);
// Returns blank 200 response
return ResponseEntity.status(HttpStatus.CREATED)
.body(
// I haven't got far to creating a response, so do not mind the "Error".
new Error("Created", "Stand-in until created proper response")
);
}
}
Response.java
public interface Response {}
Error.java
public class Error implements Response {
private String errorType;
private String errorMessage;
public Error(String errorType, String errorMessage) {
this.errorType = errorType;
this.errorMessage = errorMessage;
}
public String getErrorType() {
return errorType;
}
public void setErrorType(String errorType) {
this.errorType = errorType;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
If anyone needs anything else, let me know, but this should be enough to cover.
As I stated, new to Spring, and forgot to change the return type for my controller layer:
SampleController.java
#PostMapping
public ResponseEntity<Response> createData(#RequestBody Data data) {
return this.sampleService.registerData(data);
}
I need to get json data response based on SECRET CODE with POST method, would you please solve my issue, thanks in advance.
I have been facing with many problems with this POST method of Secret Code to get the JSON Response
public class MainActivity extends AppCompatActivity {
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listViewHeroes);
getQuestions();
}
private void getQuestions() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.BASE_URL)
.addConverterFactory(GsonConverterFactory.create()) //Here we are using the GsonConverterFactory to directly convert json data to object
.build();
ApiInterface api = retrofit.create(ApiInterface.class);
RequestModel requestModel = new RequestModel();
requestModel.setSecretCode("341977082");
Call<List<ModelObjects>> call = api.getQuestions();
call.enqueue(new Callback<List<ModelObjects>>() {
#Override
public void onResponse(Call<List<ModelObjects>> call, Response<List<ModelObjects>> response) {
List<ModelObjects> questionsList = response.body();
String[] questions = new String[questionsList.size()];
for (int i = 0; i < questionsList.size(); i++) {
questions[i] = questionsList.get(i).getQues_No();
}
listView.setAdapter(new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, questions));
}
#Override
public void onFailure(Call<List<ModelObjects>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});}}
Here is the interface and where I am passing the URL that contains parent and extension
public interface ApiInterface {
String BASE_URL = "";
#POST("QuestionsList")
Call<List<ModelObjects>> getQuestions();}
Here is the response Model
public class ModelObjects {
#SerializedName("Ques_No")
private String Ques_No;
public ModelObjects(String ques_No) {
Ques_No = ques_No;
}
public String getQues_No() {
return Ques_No;
}
public void setQues_No(String ques_No) {
Ques_No = ques_No;
}}
Here is the Request Model
public class RequestModel {
private String SecretCode;
public RequestModel(String secretCode) {
SecretCode = secretCode;
}
public RequestModel() {
}
public String getSecretCode() {
return SecretCode;
}
public void setSecretCode(String secretCode) {
SecretCode = secretCode;
}}
Here you have defined RequestModel but you are not passing it to the api call. Post request should have body.
So specify #Body while defining the api call as below.
#POST("QuestionsList")
Call<List<ModelObjects>> getQuestions(#Body RequestModel model);
Then while calling the getQuestion() pass the model.
RequestModel requestModel = new RequestModel();
requestModel.setSecretCode("341977082");
Call<List<ModelObjects>> call = api.getQuestions(requestModel);
Update :
update your ModelObject as below.
public class ModelObjects {
#SerializedName("Ques_No")
String Ques_No;
#SerializedName("Question")
String Ques;
#SerializedName("Answer")
String answer;
//same for other params as well
}
What can i see it, you are creating object of RequestModel class, but you are not passing it anywhere. If you want to send the secretCode along with the post network call, then you'll have to pass this requestModel instance to the call.
public interface ApiInterface {
String BASE_URL = "";
#POST("QuestionsList")
Call<List<ModelObjects>> getQuestions(#Body RequestModel requestModel);
}
then you can call this method and can pass this requestModel Object by
Call<List<ModelObjects>> call = api.getQuestions(requestModel);
If you want to access the first object you can do it by
List<ModelObjects> questionsList = response.body();
ModelObject obj = questionList.get(0);
String question = obj.getQues_No();
This question is going to be the first question.
I have a problem with parsing my custom response because the I have a response with Localization properties.
I am recieving a response that looks something like this:
[
{
"id": "dummyID1",
"name.en_US": "dummyNameEn1",
"name.fi_FI": "dummyNameFi1"
},
{
"id": "dummyID2",
"name.en_US": "dummyNameEn2",
"name.fi_FI": "dummyNameFi2"
},
{
"id": "dummyID3",
"name.en_US": "dummyNameEn3",
"name.fi_FI": "dummyNameFi3"
}...
]
And to parse that I have created a custom class Device.java:
public class Device {
public String id;
public LocalizedString name;
public Device(String id, LocalizedString name) {
this.id = id;
this.name = name;
}
//Getters and setters
}
Now here we have a custom object named LocalizedString.java:
public class LocalizedString implements Parcelable {
public static final Creator<LocalizedString> CREATOR = new Creator<LocalizedString>() {
#Override
public LocalizedString createFromParcel(Parcel in) {
return new LocalizedString(in);
}
#Override
public LocalizedString[] newArray(int size) {
return new LocalizedString[size];
}
};
private String en_US;
private String fi_FI;
public LocalizedString(String en, String fi) {
this.en_US = en;
this.fi_FI = fi;
}
protected LocalizedString(Parcel in) {
en_US = in.readString();
fi_FI = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(en_US);
dest.writeString(fi_FI);
}
//Getters, setters
}
Now in my response I want to create a list of Device's but it does not seem to understand how the ´LocalizedString´ works. Since my request is returning a <List<Device>> I cannot really customly parse it either.
Here is how I try to parse it:
Call<List<Device>> call = getMainActivity().getRestClient().getDevices();
call.enqueue(new Callback<List<Device>>() {
#Override
public void onResponse(Call<List<Device>> call, Response<List<Device>> response) {
if (isAttached()) {
if (response.isSuccessful()) {
// get data
List<Device> items = response.body();
}
}
}
#Override
public void onFailure(Call<List<Device>> call, Throwable t) {
if (isAttached()) {
Logger.debug(getClass().getName(), "Could not fetch installation document devices past orders", t);
getMainActivity().showError(R.string.error_network);
}
}
});
And:
#GET("document/devices")
Call<List<Device>> gettDevices();
What am I supposed to do in this situation to bind the name to the Device and later be able to either get en_US or fi_FI.
Better you can write it like this
public class Device {
#SerializedName("id")
public String id;
#SerializedName("name.en_US")
public String en;
#SerializedName("name.fi_FI")
public String fi;
public Device(String id, String english, String fi) {
this.id = id;
this.en = english;
this.fi = fi;
}
//Getters and setters
}
If you can control the source of the JSON, then a modification of that JSON structure is easy to solve your problem.
If you can not, the one way we can use to solve your problem is to use Jackson and custom deserializer:
public class DeviceDeserializer extends StdDeserializer<Device> {
public DeviceDeserializer() {
this(null);
}
public DeviceDeserializer(Class<?> vc) {
super(vc);
}
#Override
public Device deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
String id = getStringValue(node, "id");
String en = getStringValue(node, "name.en_EN");
String fi = getStringValue(node, "name.fi_FI");
LocalizedString localized = new LocalizedString(en, fi);
return new Device(id, localizedString);
}
private String getStringValue(JsonNode node, String key) {
// Throws exception or use null is up to you to decide
return Optional.ofNullable(node.get("id"))
.map(JsonNode::asText)
.orElse(null);
}
}
Manually register the deserializer yourself or using the annotation:
#JsonDeserialize(using = DeviceDeserializer.class)
public class Device {
...
Note that you must enable retrofit jackson converter plugin: (see the Retrofit Configuration part)
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(JacksonConverterFactory.create())
.build();
Read this: Get nested JSON object with GSON using retrofit
I am developing an application where I want to hit the web services and get the data. I am using Google Volley to hit the web service. I am doing it all right but unable to parse JSON using GSON. I am unable to understand where I am doing it wrong.
Here is the URL of Web Services
Here is what I am doing
RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
Request.Method.GET,
"https://api.github.com/repos/crashlytics/secureudid/issues",
null,
new MyListner(),
new MyErrorListner()
);
requestQueue.add(jsonObjectRequest);
}
class MyListner implements Response.Listener<JSONObject>
{
#Override
public void onResponse(JSONObject response) {
Gson gson = new Gson();
Results results = gson.fromJson(response.toString(), Results.class);
for(Test t : results.getmResults())
{
Log.e("Tag", t.toString());
}
}
}
class MyErrorListner implements Response.ErrorListener
{
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error", error.getMessage());
}
}
The other classes are given below
public class Results {
private ArrayList<Test> mResults;
public void setResults(ArrayList<Test> results)
{
mResults = results;
}
public ArrayList<Test> getmResults()
{
return mResults;
}
}
public class Test {
#SerializedName("title")
private String mTitle;
#SerializedName("user")
private User mUser;
#SerializedName("created_at")
private String mCreatedAt;
#SerializedName("body")
private String mBody;
#SerializedName("updated_at")
private String mUpdatedAt;
public String getmBody() {
return mBody;
}
public void setmBody(String mBody) {
this.mBody = mBody;
}
public String getmUpdatedAt() {
return mUpdatedAt;
}
public void setmUpdatedAt(String mUpdatedAt) {
this.mUpdatedAt = mUpdatedAt;
}
public String getmCreatedAt() {
return mCreatedAt;
}
public void setmCreatedAt(String mCreatedAt) {
this.mCreatedAt = mCreatedAt;
}
public User getmUser() {
return mUser;
}
public void setmUser(User mUser) {
this.mUser = mUser;
}
public String getmTitle() {
return mTitle;
}
public void setmTitle(String mTitle) {
this.mTitle = mTitle;
}
#Override
public String toString() {
return mTitle + " " + mBody + " " + mCreatedAt + " " + mUpdatedAt + " " + mUser.getmLogin() + " ";
}
}
public class User {
#SerializedName("login")
private String mLogin;
public String getmLogin() {
return mLogin;
}
public void setmLogin(String mLogin) {
this.mLogin = mLogin;
}
}
Here is the error what I am getting
org.json.JSONException: Value [{"url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/28","repository_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid","labels_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/28\/labels{\/name}","comments_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/28\/comments","events_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/28\/events","html_url":"https:\/\/github.com\/crashlytics\/secureudid\/pull\/28","id":222258999,"number":28,"title":"Fix broken headings in Markdown files","user":{"login":"bryant1410","id":3905501,"avatar_url":"https:\/\/avatars3.githubusercontent.com\/u\/3905501?v=4","gravatar_id":"","url":"https:\/\/api.github.com\/users\/bryant1410","html_url":"https:\/\/github.com\/bryant1410","followers_url":"https:\/\/api.github.com\/users\/bryant1410\/followers","following_url":"https:\/\/api.github.com\/users\/bryant1410\/following{\/other_user}","gists_url":"https:\/\/api.github.com\/users\/bryant1410\/gists{\/gist_id}","starred_url":"https:\/\/api.github.com\/users\/bryant1410\/starred{\/owner}{\/repo}","subscriptions_url":"https:\/\/api.github.com\/users\/bryant1410\/subscriptions","organizations_url":"https:\/\/api.github.com\/users\/bryant1410\/orgs","repos_url":"https:\/\/api.github.com\/users\/bryant1410\/repos","events_url":"https:\/\/api.github.com\/users\/bryant1410\/events{\/privacy}","received_events_url":"https:\/\/api.github.com\/users\/bryant1410\/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2017-04-17T23:26:47Z","updated_at":"2017-04-17T23:26:47Z","closed_at":null,"author_association":"NONE","pull_request":{"url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/pulls\/28","html_url":"https:\/\/github.com\/crashlytics\/secureudid\/pull\/28","diff_url":"https:\/\/github.com\/crashlytics\/secureudid\/pull\/28.diff","patch_url":"https:\/\/github.com\/crashlytics\/secureudid\/pull\/28.patch"},"body":"GitHub changed the way Markdown headings are parsed, so this change fixes it.\n\nSee [bryant1410\/readmesfix](https:\/\/github.com\/bryant1410\/readmesfix) for more information.\n\nTackles bryant1410\/readmesfix#1\n"},{"url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/13","repository_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid","labels_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/13\/labels{\/name}","comments_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/13\/comments","events_url":"https:\/\/api.github.com\/repos\/crashlytics\/secureudid\/issues\/13\/events","html_url":"https:\/\/github.com\/crashlytics\/secureudid\/issues\/13","id":3923240,"number":13,"title":"Not working with ARC","user":{"login":"SaschaMoellering","id":1321549,"avatar_url":"https:\/\/avatars0.githubusercontent.com\/u\/1321549?v=4","gravatar_id":"","url":"https:\/\/api.github.com\/users\/SaschaMoellering","html_url":"https:\/\/github.com\/SaschaMoellering","followers_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/followers","following_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/following{\/other_user}","gists_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/gists{\/gist_id}","starred_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/starred{\/owner}{\/repo}","subscriptions_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/subscriptions","organizations_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/orgs","repos_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/repos","events_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/events{\/privacy}","received_events_url":"https:\/\/api.github.com\/users\/SaschaMoellering\/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":10,"created_at":"20
You are trying to parse an array of object (from your webservices) to an object containing a property mResults which is an array of object (Test);
Instead of using Results class during parsing you need to directly use an ArrayList of Test:
Results results = gson.fromJson(response.toString(), Results.class);
should be
ArrayList<Test> results = gson.fromJson(response.toString(), new TypeToken<ArrayList<Test>>(){}.getType());
As ArrayList is a generic it's not possible to use ArrayList<Test>.class to get a representation of the data type, we must use TypeToken. What is TypeToken?
TypeToken represents a generic type T. Java doesn't yet provide a way to
represent generic types, so this class does. Forces clients to create
a subclass of this class which enables retrieval the type information
even at runtime.
getType returns the type of the class used to build TypeToken and so we can use it in gson fromJson() parsing method.
--
Second problem:
Your are using JsonObjectRequest but server response is a Json array so you need to use JsonArrayRequest and so update MyListner to use JSONArray instead of JSONObject.
BUT
As your are parsing server response manually you can use StringRequest and so avoid parsing step of Volley.
StringRequest jsonObjectRequest = new StringRequest(
Request.Method.GET,
"https://api.github.com/repos/crashlytics/secureudid/issues",
new MyListner(),
new MyErrorListner()
);
and MyListner is now directly using String:
class MyListner implements Response.Listener<String> {
#Override
public void onResponse(String response) {
Gson gson = new Gson();
ArrayList<Test> results = gson.fromJson(response, new TypeToken<ArrayList<Test>>() {}.getType());
for (Test t : results) {
Log.e("Tag", t.toString());
}
}
}
How to convert given json response
{
"name" : "John",
"surname" : "Doe",
"location" : {
"name" : "Paris",
"desc" : "Welcome to Paris"
}
}
into
class Person
{
String name;
String surname;
Location location; // new Location(String name, String desc)
}
It's all about nested Location class that is inside Person class
Use #Expose or #SerializedName annotation like
class Person
{
#SerializedName("name")
String name;
#SerializedName("surname")
String surname;
#SerializedName("location")
Location location; // new Location(String name, String desc)
}
and Location class like
class Location
{
#SerializedName("name")
String name;
#SerializedName("desc")
String desc;
}
Add getter and setter method for accessing data
Use a combination of Gson + Retrofit.
First of all use the annotation #SerializedName("yourFieldName") that Retrofit provides in the fields of your model class.
Init your Gson configuration with a RuntimeTypeAdapterFactory:
RuntimeTypeAdapterFactory<Person> itemFactory = RuntimeTypeAdapterFactory
.of(Person.class) // The field that defines the type
.registerSubtype(Location.class, "location")
.registerSubtype(YourSubclass.class) // if the flag equals the class name, you can skip the second parameter.
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(itemFactory)
.create();
Then you init Retrofit:
Retrofit.Builder builder = new Retrofit.Builder();
builder.baseUrl(BASE_URL);
builder.addConverterFactory(GsonConverterFactory.create(gson));
Retrofit retrofit = builder.build();
First get an API and get its JSON output by Advance REST Client which is a Chrome Extension. Now put that output to JSON to POJO converter
and you'll get your POJO Classes. Paste them to your project. Make an interface`
/**
* Get Data
*
* #param body Holds the JSON payloads
* #return Formatted data
*/
#POST("JobSpotAPI/getUserInterviewSchedule")
Call<POJOClass> getData(#Body JsonObject body);
and setup a Client
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
Create a Recycler view setup its adapter and all. Just add a few new methods like-
public void updateAnswers(List<Item> items) {
mItems = items;
notifyDataSetChanged();
}
private Item getItem(int adapterPosition) {
return mItems.get(adapterPosition);
}
Setup Utility class to call the interface.
public class ApiUtils {
public static final String BASE_URL = "https://base_url/";
public static Interface_name methodName() {
return RetrofitClient.getClient(BASE_URL).create(Interface_name.class);
}}
Declare the Interface in your Activity
Interface_name obj = ApiUtils.methodName();
If you have some payloads then attach them to you request. Before that you need a JSON string to pass to API request. To make a JSON Payload.
private JsonObject makeJsonObjectPayload() {
JsonObject requestBean = new JsonObject();
requestBean.addProperty("key", value);
requestBean.addProperty("key", value);
requestBean.addProperty("key", value);
requestBean.addProperty("key", value);
return requestBean;
Pass the API request
obj.getData(makeJsonObjectPayload()).enqueue(new Callback<POJOClass>() {
#Override
public void onResponse(Call<POJOClass> call, Response<POJOClass> response) {
if(response.isSuccessful()) {
mAdapter.updateAnswers(response.body().getItems());
Log.d("MainActivity", "posts loaded from API");
}else {
int statusCode = response.code();
// handle request errors depending on status code
}
}
#Override
public void onFailure(Call<UserDataPOJOClass> call, Throwable t) {
//showErrorMessage();
Log.d("API ERROR",""+t.getMessage());
Log.d("MainActivity", "error loading from API");
}
});