I am pretty new to Java.
I want to model this request for a batch request to Microsoft graphAPI.
{"requests":[
{"id":"employeeId","method":"GET","url":"/me/employeeId"},
{"id":"thumbnailPhoto","method":"GET","url":"/me/photo/$value"}]
}
So "requests" is an array of BatchRequest object.
What I have currently:
// BatchRequest object
public class BatchRequest
{
private String id;
private String method;
private String url;
public BatchRequest(String id, String method, String url)
{
this.id = id;
this.method = method;
this.url = url;
}
// getters and setters below
}
private List<BatchRequest> requests;
#Override
public UserInfoResponse callGraphApi()
{
BatchRequest employeeId = new BatchRequest("employeeId", "GET", "/me/employeeId");
BatchRequest photo = new BatchRequest("thumbnailPhoto", "GET", "/me/photo/$value");
requests.add(employeeId);
requests.add(photo);
return callGraphApi(requests);
}
Is this how I would model the JSON?
Found this Jsonschema2pojo while i was trying to figure out how to model my Json response into java objects in android app development. Install gson or jackson in your project and it'll take care of the things under the hood.
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class BatchRequest {
#SerializedName("requests")
#Expose
private List<Request> requests = null;
public List<Request> getRequests() {
return requests;
}
public void setRequests(List<Request> requests) {
this.requests = requests;
}
}
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Request {
#SerializedName("id")
#Expose
private String id;
#SerializedName("method")
#Expose
private String method;
#SerializedName("url")
#Expose
private String url;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
Sure. The task of turning an instance of a simple java object into a bunch of JSON, as well as the job of turning a bunch of JSON, combined with a list of simple java classes into instances of those classes, is called 'marshalling'. You'll need a library to do it; the popular ones are Jackson and GSON.
Related
I'm using GitHub API to show in my application the most starred repository and their names and avatar and description in recyclerView but when I lunch the app everything working but the avatar_url and login return Null.
this is a JSON from Github API
https://api.github.com/search/repositories?q=created:%3E2019-10-01&sort=stars&order=desc
I tried this :
client class:
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class Client {
public static final String BASE_URL="https://api.github.com";
public static Retrofit retrofit=null;
public static Retrofit getClient()
{
if(retrofit==null)
{
retrofit=new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
}
Service Class:
package com.example.gethubapi.api;
import com.example.gethubapi.model.ItemResponse;
import retrofit2.Call;
import retrofit2.http.GET;
public interface Service {
#GET("/search/repositories?q=created:>2017-10-22&sort=stars&order=desc&page=2")
Call<ItemResponse> getItems();
}
Item class
here is the problem if u checked the jSON file in link above you will find a child object from item called owner and i cant select the name of avatar_url and owner name directly
import com.google.gson.annotations.SerializedName;
public class Item {
#SerializedName("avatar_url")
#Expose
private String avatarUrl;
#SerializedName("name")
#Expose
private String name;
#SerializedName("description")
#Expose
private String description;
#SerializedName("login")
#Expose
private String owner;
#SerializedName("stargazers_count")
#Expose
private int stargazers;
public Item(String avatar_url,String name,String description,String owner,int stargazers )
{
this.avatarUrl=avatar_url;
this.name=name;
this.description=description;
this.owner=owner;
this.stargazers=stargazers;
}
public String getAvatarUrl()
{
return avatarUrl;
}
public String getName()
{
return name;
}
public String getDescription()
{
return description;
}
public String getOwner()
{
return owner;
}
public int getStargazers()
{
return stargazers;
}
}
Looking at the JSON response, the Owner object is part of the Item object. meaning it's nested in the Item object.
public class Owner {
#SerializedName("avatar_url")
#Expose
private String avatarUrl;
#SerializedName("login")
#Expose
private String login;
public Owner(){}
public void setAvatarUrl(String avatar_URL){
this.avatarUrl = avatar_URL;
}
pubic String getAvatarUrl(){
return avatarUrl;
}
public String getLogin(){
return login;
}
public void setLogin(String login){
this.login = login;}
}
public class Item {
#SerializedName("name")
#Expose
private String name;
#SerializedName("description")
#Expose
private String description;
#SerializedName("owner")
#Expose
private Owner owner;
#SerializedName("stargazers_count")
#Expose
private int stargazers;
.........
}
Since the login and avatar_url is under owner object.
You need to create a separate class for owner object , just like you did for a single item.
And don't forget to mention the object class in your Item class.
In my case the stargazer spelling was wrong, just correct the spelling
example:- from
stargazer_count
to
stargazers_count.
Am trying to automate Jira Issue Creation via REST API with Java Rest Assured. The following are my code snippets.
I need to reframe the following JSON in Java and pass it to the Body.
{
"fields": {
"project": {
"id": "13204"
},
"summary": "welcome to testing1",
"issuetype": {
"id": "3"
},
"reporter": {
"name": "parthiban.selvaraj"
},
"priority": {
"id": "3"
},
"description": "description",
"customfield_10201": {
"id": "10608"
}
}
}
Below is my Java code with getter and setter:
package jira;
import com.google.gson.Gson;
import io.restassured.RestAssured;
import io.restassured.authentication.PreemptiveBasicAuthScheme;
import io.restassured.http.ContentType;
import io.restassured.http.Method;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import java.util.List;
public class home {
public static void main (String args[]){
System.out.println("Welcome");
RestAssured.baseURI = "http://##.###.##.##:####/jira/rest/api/2/issue/";
PreemptiveBasicAuthScheme authScheme = new PreemptiveBasicAuthScheme();
authScheme.setUserName("########");
authScheme.setPassword("#######");
RestAssured.authentication = authScheme;
getterSetter values=new getterSetter();
values.setProject(13204);
values.setSummary("Checking via REST Assured");
values.setIssueType(3);
values.setReporter("#######");
values.setPriority(3);
values.setDescription("Welcome to JAVA World");
//Updating sprint name custom field value
values.setCustomfield_10201(10608);
Gson gson=new Gson();
String json= gson.toJson(values);
System.out.println("JSON Values " + json);
RequestSpecification httpRequest = RestAssured.given().header("Content-Type",
"application/json").body(json);
System.out.println(httpRequest + " Request ");
Response response = httpRequest.request(Method.POST, "");
System.out.println(response.getStatusCode());
String responseBody = response.getBody().asString();
System.out.println("response " + responseBody);
JsonPath jsonPath = new JsonPath(responseBody);
}
}
Getter and Setter File:
package jira;
import javax.xml.bind.annotation.XmlRootElement;
//#XmlRootElement
public class getterSetter {
private int project;
private int issueType;
private String reporter;
private String summary;
private int priority;
private String description;
private int customfield_10201;
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public void setProject(int project){
this.project=project;
}
public int getProject() {
return project;
}
public int getIssueType() {
return issueType;
}
public void setIssueType(int issueType) {
this.issueType = issueType;
}
public String getReporter() {
return reporter;
}
public void setReporter(String reporter) {
this.reporter = reporter;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getCustomfield_10201() {
return customfield_10201;
}
public void setCustomfield_10201(int customfield_10201) {
this.customfield_10201 = customfield_10201;
}
}
I understand JSON format which I am passing through request Body is wrong. Can anyone help me to pass correct JSON format in Request Body.
I tested in Postman with the above JSON format Issue created successfully in my Instance.
For the above code am hitting with
response code 500 and Internal Server Error.
According to the JSON string as the payload to create Jira issue, you can directly create several corresponding classes as follows:
class IssueInfo {
private Field fields;
//general getters and setters
}
class Field {
private Project project;
private String summary;
private IssueType issuetype;
private Reporter reporter;
private Priority priority;
private String description;
private Customfield10201 customfield_10201;
//general getters and setters
}
class Project {
private String id;
//general getters and setters
}
class IssueType {
private String id;
//general getters and setters
}
class Reporter {
private String name;
//general getters and setters
}
class Priority {
private String id;
//general getters and setters
}
class Customfield10201 {
private String id;
//general getters and setters
}
After assigning value of each required field, you can pass the instance of IssueInfo as request body.
I have a REST service and it's response can be change according to status. For example; When I send a request and the response can be two types. The first one like that
{
"status": "success",
"user": {
"user_id": 3554,
"full_name": "test",
"email_address": "test#test1.com",
"end_date": null
}
}
The second type is like that
{
"status": "failure",
"reason": "email_taken"
}
The response according to "status" which comes with response. I searched this problem and find some solutions (custom converter, set custom converter etc.) But I think these are not clear enough . Are there any solution like that; if "status" is success, convert to json response to User model, else convert json response to FailureModel?
Retrofit dependency : implementation 'com.squareup.retrofit:retrofit:1.9.0'
If the only solution is custom converter, please explain it clearly because I am really new on this topic.
It is possible with custom json deserializer. You only have user when the status is success in case it is not you have the reason. In case you have status error and try to access user its null.
public class CustomConvertor implements JsonDeserializer<Response> {
#Override
public Response deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Gson gson = new Gson();
Response response = gson.fromJson(json, Response.class);
if (response.getStatus().equals("success")) {
// The full response as a json object
final JsonObject jsonObject = json.getAsJsonObject();
// The user attribute in the JSON received
final JsonElement jsonElement = jsonObject.get("user");
User user = gson.fromJson(jsonElement, User.class);
response.setUser(user);
}else{
// you could do this
// not needed as json is deserialized to Response already
// just for the example
final JsonObject jsonObject = json.getAsJsonObject();
String reason = jsonObject.getAsJsonPrimitive("reason").getAsString();
response.setReason(reason);
}
return response;
}
}
The retrofit part
GsonBuilder gsonBuilder =new GsonBuilder();
gsonBuilder.registerTypeAdapter(Response.class, new CustomConvertor());
Gson gson = gsonBuilder.create();
GsonConverterFactory gsonConverterFactory = GsonConverterFactory.create(gson);
Retrofit retrofit = new Retrofit.Builder()
...// other setups
.addConverterFactory(gsonConverterFactory).build();
Then
// service is my case
Service service = retrofit.create(Service.class);
// call enqueue in your case.for testing i used mockwebserver
Response response = service.exampleJson().execute().body();
Log.i("User: ","" + response.geUser().getFullname());
in case of error
Log.i("Error: ","" + response.getReason());
You can get your pojos from http://www.jsonschema2pojo.org/
Pojo's
Response.java
public class Response {
#SerializedName("status")
#Expose
private String status;
#SerializedName("user")
#Expose
private User user;
#Expose
#SerializedName("reason")
private String reason;
public void setReason(String reason) {
this.reason = reason;
}
public String getReason() {
return reason;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
User.java
public class User {
#SerializedName("user_id")
#Expose
private int userId;
#SerializedName("full_name")
#Expose
private String fullName;
#SerializedName("email_address")
#Expose
private String emailAddress;
#SerializedName("end_date")
#Expose
private Object endDate;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public Object getEndDate() {
return endDate;
}
public void setEndDate(Object endDate) {
this.endDate = endDate;
}
}
The other way
Call<Response> auth = .// setup
auth.enqueue(new Callback<Response>() {
#Override
public void onResponse(Call<Response> call, Response<Response> response) {
if (response.isSuccessful() ) {
Response respojo = response.body();
if(respojo.getStatus().equals("success"){
Log.i("User: ","" + respojo.getUser().getFullname());
}else {
Log.i("Error: ","" + respojo.getReason());
}
}
} else {
response.errorBody();
}
}
#Override
public void onFailure(Call<Response> call, Throwable t) {
t.printStackTrace();
}
});
You can use a unique model and handle both cases with it :
public class UserResponseModel{
private String status;
private String reason;
private UserModel user;
// getter/setter
boolean isFailure(){
return status == "failure"
}
boolean isSuccess(){
return status == "success"
}
}
you may then do
UserResponseModel response
if( response.isSuccess() ) // do whatever with response.user
else // do whatever with response.reason
With your retrofit 2.0 best idea is to use Gson converter. Just add #Nullable annotation with your optional json key (in your case user and reason) so it does not crash while parsing or does not generate nullpointer exception. So your model class look like as follows.
public class YourModelClass {
#SerializedName("status")
#Expose
public String status;
#Nullable
#SerializedName("user")
#Expose
public User user;
#Nullable
#SerializedName("reason")
#Expose
public String reason;
public class User {
#SerializedName("user_id")
#Expose
public Integer userId;
#SerializedName("full_name")
#Expose
public String fullName;
#SerializedName("email_address")
#Expose
public String emailAddress;
#SerializedName("end_date")
#Expose
public Object endDate;
}
}
In your Activity or fragment where you are requesting parse it as follows
#Override
public void onResponse(Call<YourModelClass> call, Response<YourModelClass> response) {
if(response.body.yourModelClass.status.equals("succ")) {
User changesList = response.body().user;
//perform action with user data
} else {
Log.d("failer", response.body().reason)
}
}
#Override
public void onFailure(Call<YourModelClass> call, Throwable t) {
t.printStackTrace();
}
I hope its work for you.
Use android studio plugin DTO Genrater for creating pojo.
You can have an englobing class for this, for example:
public class Foo {
String status;
String reason;
UserModel user;
// Constructors, getter/setter, others
// ...
}
then call Retrofit like,
Call<Foo> callToYourAPI();
and when you want to have a user:
if (foo.reason == "success") // or if (foo.user != null)
// do something with foo.user
The conversion is done automatically in such a case. If your problem was having a field that can be of one type or another, you would have needed a converter.
I am using Retrofit and ActiveAndroid ORM in my application. I have the following Model class:
#Table(name = "formresource")
public class FormResource extends Model implements Serializable{
#Column(name="name")
#SerializedName("name")
#Expose
private String name;
#Column
#SerializedName("resources")
#Expose
private List<FormResource> resources = new ArrayList<FormResource>();
#Column(name = "valueReference")
#SerializedName("valueReference")
#Expose
private String valueReference;
#Column(name = "uuid")
#SerializedName("uuid")
#Expose
private String uuid;
#Column(name = "display")
#SerializedName("display")
#Expose
private String display;
#Column(name = "links")
#SerializedName("links")
#Expose
private List<Link> links = new ArrayList<Link>();
public FormResource()
{
super();
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getDisplay() {
return display;
}
public void setDisplay(String display) {
this.display = display;
}
public List<Link> getLinks() {
return links;
}
public void setLinks(List<Link> links) {
this.links = links;
}
public String getValueReference() {
return valueReference;
}
public void setValueReference(String valueReference) {
this.valueReference = valueReference;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<FormResource> getResources() {
return resources;
}
public void setResources(List<FormResource> resources) {
this.resources = resources;
}
}
Now, I obtain the Formresources once while starting the application and save it. Then in another activity I use the saved formresources to populate a listview. This much works fine. Now, I want to access the nested formresources like this:
formresourcelist.get(position).getResources();
This always returns a blank list of List<FormResource> . What should I do to properly save and retrieve this list? I need to maintain compatibility with Retrofit at the same time.
I think I found a workaround. I made the following changes in the Model Class:
#Table(name = "formresource")
public class FormResource extends Model implements Serializable{
Gson gson=new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Type formresourcelistType = new TypeToken<List<FormResource>>(){}.getType();
#SerializedName("resources")
#Expose
private List<FormResource> resources = new ArrayList<FormResource>();
#Column(name = "resources")
#Expose
private String resourcelist;
public List<FormResource> getResources() {
return resources;
}
public void setResources(List<FormResource> resources) {
this.resources = resources;
}
public void setResourcelist()
{
this.resourcelist=gson.toJson(resources,formresourcelistType);
}
public List<FormResource> getResourceList() {
List<FormResource> resourceList=gson.fromJson(this.resourcelist,formresourcelistType);
return resourceList;
}
}
Basically I am serializing the ArrayList and persisting it as a String in the DB. While saving a FormResource, I do the following:
formresourceObject.setResourcelist();
formresourceObject.save();
Since you're using Retrofit to populate the FormResource data, you should not initialize any fields inside the model.
This line is the problem :
private List<FormResource> resources = new ArrayList<FormResource>();
try removing the initialization and just declare the field like :
private List<FormResource> resources;
and then try calling formresourcelist.get(position).getResources();
Good luck!
I have a very basic problem.
I read though the LibGDX documentation a few times regarding JSON and Google around for an answer but it still does't work..
Basically I'm pulling json from a server like such which works as:
{"id":1,"facebook_id":"23432232","json":"{\"json\":\"test\"}"}
I have a class like this:
public class ServerJson
{
public static final String NAME = "ServerJson";
private int id;
private String facebookID;
private String json;
public ServerJson(){}
public ServerJson(int id, String facebookID, String json)
{
this.id = id;
this.facebookID = facebookID;
this.json = json;
}
public int getId() {
return id;
}
public String getFacebookID() {
return facebookID;
}
public String getJson() {
return json;
}
When I try to parse the code, it doesn't work. I get null:
String resultString = httpResponse.getResultAsString(); //{"id":1,"facebook_id":"23432232","json":"{\"json\":\"test\"}"}
Json json = new Json();
ServerJson serverJson = json.fromJson(ServerJson.class, resultString);
log(serverJson.getFacebookID()); //<< Is null.
Make sure the fields of your object class match up with the fields of the json object.