How to create an rest api which accepts nested api as request - json

I am creating a rest api in spring boot as well as in jersey. I need to pass a nested JSON structure as request. I have no idea how to do it.
The nested structure is below,
{
"student": "",
"groupId": "a1",
"standard": "Fifth",
"isPassed": true,
"section": "A",
"data": {
"name": "Abcd",
"age": "11"
},
"additional": {
"Personal": {
"1": {
"address": {
"Home": [
"xys"
],
"Permanent": [
"xyz"
],
"Language": [
"English",
"French"
]
},
"street": "5",
"Mother": null,
"Father": null
}
}
"state": "xyz",
"Sibblings": true
}
}
I am expecting the rest call to accept this structure.

You can try something like this, first create request dto which will map the json to the DTO
import java.util.List;
public class RequestDTO {
private String student;
private String groupId;
private String standard;
private Boolean isPassed;
private String section;
private UserData data;
private Additional additional;
public String getStudent() {
return student;
}
public void setStudent(String student) {
this.student = student;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public String getStandard() {
return standard;
}
public void setStandard(String standard) {
this.standard = standard;
}
public Boolean getPassed() {
return isPassed;
}
public void setPassed(Boolean passed) {
isPassed = passed;
}
public String getSection() {
return section;
}
public void setSection(String section) {
this.section = section;
}
public UserData getData() {
return data;
}
public void setData(UserData data) {
this.data = data;
}
public Additional getAdditional() {
return additional;
}
public void setAdditional(Additional additional) {
this.additional = additional;
}
}
class UserData {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Additional{
private Personal personal;
private String state;
private Boolean Sibblings;
public Personal getPersonal() {
return personal;
}
public void setPersonal(Personal personal) {
this.personal = personal;
}
}
class Personal{
private Address address;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
class Address{
private List<String> Home;
private List<String> Permanent;
private List<Language> Language;
public List<String> getHome() {
return Home;
}
public void setHome(List<String> home) {
Home = home;
}
}
enum Language{
English,French;
}
Second create a API handler which will accept this request
#RestController
#RequestMapping("/api")
public class AdminController {
#RequestMapping(value = "/test", method = RequestMethod.POST)
public RequestDTO postData(#RequestBody RequestDTO requestDTO) {
logger.info("Body---->", requestDTO);
return requestDTO;
}
}
You can test it via below curl
curl -X POST \
http://localhost:<PORT>/<context>/api/test \
-H 'Content-Type: application/json' \
-H 'Postman-Token: 7b66a9cf-8b69-4555-9bb2-1c186bff368d' \
-H 'cache-control: no-cache' \
-d '{
"student": "",
"groupId": "a1",
"standard": "Fifth",
"isPassed": true,
"section": "A",
"data": {
"name": "Abcd",
"age": "11"
},
"additional": {
"Personal": {
"address": {
"Home": [
"xys"
],
"Permanent": [
"xyz"
],
"Language": [
"English",
"French"
]
},
"street": "5",
"Mother": null,
"Father": null
},
"state": "xyz",
"Sibblings": true
}
}'
I will suggest you to go though offical docs for better understanding

class Data
{
private String name;
private Integer age;
}
class Student{
private String student;
private String groupId;
private String standard;
private Boolean isPassed;
private String section;
private Data data;
private Additional additional;
}
Here is something to get started with. Further nesting has to be done the similar way

Related

Spring + Android(Retrofit2) GET request returning null

I saw a lot of similar problems, but after many tries, still I don't know why my retrofit Get request returning null. I tried code this with many tutorials, spent one day on solution. URL from code should return all of cd's in database.
Below is client code in onCreate method in HomeFragment.class
Call<CD> call = RetrofitClient
.getInstance().getUserClient().getDataCD(token, "cds");
call.enqueue(new Callback<CD>() {
#Override
public void onResponse(Call<CD> call, Response<CD> response) {
if(!response.isSuccessful()){
System.out.println("Code: " + response.code());
return;
}else{
System.out.println(response.body());
}
}
#Override
public void onFailure(Call<CD> call, Throwable t) {
System.out.println(t.getMessage());
}
});
JSON model:
"cd": {
"artist": "string",
"cdtracks": [
{
"artist": "string",
"cd": [
null
],
"genre": "string",
"id": 0,
"releaseDate": 0,
"title": "string"
}
],
"comment": "string",
"comments": [
{
"content": "string",
"id": 0,
"user": {
"active": true,
"authToken": "string",
"badges": "string",
"email": "string",
"id": 0,
"isActive": true,
"nick": "string",
"photoURL": "string",
"registrationDate": 0,
"role": "string",
"score": 0,
"userscd": [
null
]
}
}
],
"genre": "string",
"id": 0,
"name": "string",
"photoURL": "string",
"rating": 0,
"released": 0,
"user": [
{
"active": true,
"authToken": "string",
"badges": "string",
"email": "string",
"id": 0,
"isActive": true,
"nick": "string",
"photoURL": "string",
"registrationDate": 0,
"role": "string",
"score": 0,
"userscd": [
null
]
}
]
},
}
CD.class
public class CD {
#SerializedName("id")
#Expose
private Long id;
#SerializedName("name")
#Expose
private String name;
#SerializedName("released")
#Expose
private int released;
#SerializedName("rating")
#Expose
private float rating = 0;
#SerializedName("comment")
#Expose
private String comment;
private int ratingCount = 0;
private float sumOfRating = 0;
#SerializedName("photoURL")
#Expose
private String photoURL = "http://bobjames.com/wp-content/themes/soundcheck/images/default-album-artwork.png";
#SerializedName("artist")
#Expose
private String artist;
#SerializedName("cdtracks")
#Expose
private ArrayList<Track> cdtracks;
#SerializedName("genre")
#Expose
private String genre;
#SerializedName("user")
#Expose
private ArrayList<User> user;
#SerializedName("comments")
#Expose
private ArrayList<Comments> comments;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getReleased() {
return released;
}
public void setReleased(int released) {
this.released = released;
}
public float getRating() {
return rating;
}
public void setRating(float rating) {
this.rating = rating;
}
public String getArtist() {
return artist;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public void setArtist(String artist) {
this.artist = artist;
}
public ArrayList<Track> getCdtracks() {
return cdtracks;
}
public String getGenre() {
return genre;
}
public void setGenre(String genre) {
this.genre = genre;
}
public ArrayList<User> getUser() {
return user;
}
public void setUser(ArrayList<User> user) {
this.user = user;
}
public int getRatingCount() {
return ratingCount;
}
public void setRatingCount(int ratingCount) {
this.ratingCount = ratingCount;
}
public float getSumOfRating() {
return sumOfRating;
}
public void setSumOfRating(float sumOfRating) {
this.sumOfRating = sumOfRating;
}
public String getPhotoURL() { return photoURL; }
public void setPhotoURL(String photoURL) { this.photoURL = photoURL; }
public ArrayList<Comments> getComments() {
return comments;
}
public void setComments(ArrayList<Comments> comments) {
this.comments = comments;
}
#Override
public String toString() {
return "CD{" +
"id=" + id +
", name='" + name + '\'' +
", released=" + released +
", rating=" + rating +
", comment='" + comment + '\'' +
", ratingCount=" + ratingCount +
", sumOfRating=" + sumOfRating +
", photoURL='" + photoURL + '\'' +
", artist='" + artist + '\'' +
", cdtracks=" + cdtracks +
", genre='" + genre + '\'' +
", user=" + user +
", comments=" + comments +
'}';
}
}
I have similar built User.class, Artist.class, Track.class, Comment.class
My interface
public interface UserClient {
#POST("api/signup")
Call<User> createUser(
#Body User user
);
#Headers({ "Content-Type: application/json;charset=UTF-8"})
#POST("login")
Call<User> userLogin(
#Body Login login
);
#Headers({ "Content-Type: application/json;charset=UTF-8"})
#GET("api/{object}")
Call<CD> getDataCD(
#Header("Authorization") String authToken,
#Path("object") String object);
}
Instantiation of UserClient.class
public class RetrofitClient {
private static final String BASE_URL = "http://s416103.projektstudencki.pl:8080/";
private static RetrofitClient retrofitClient;
private Retrofit retrofit;
private Retrofit retrofitRegistration;
private RetrofitClient(){
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Authorization", "Bearer " + token)
.build();
return chain.proceed(newRequest);
}
}).build();
retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
retrofitRegistration = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
public static synchronized RetrofitClient getInstance(){
if(retrofitClient == null){
retrofitClient = new RetrofitClient();
}
return retrofitClient;
}
public UserClient getUserClient(){
return retrofit.create(UserClient.class);
}
public UserClient getUserClientRegistration(){
return retrofitRegistration.create(UserClient.class);
}
}
Your retrofit Get request is returning null, probably because your Class CD does not match correctly with JSON Model.
You should return from api, just the object inside the property "cd".
JSON Model fixed:
{
"genre": "string",
"id": 0,
"name": "string",
"photoURL": "string",
"rating": 0,
"released": 0,
(...)
}

Android - JSON parsing without the array name using Retrofit

I have json respose with no arrayname.
Below are the code till now I have done.
JSON Response
[
{
"id": 1,
"user_id": 101,
"name": "abc",
"number": 1234567890
},
{
"id": 2,
"user_id": 102,
"name": "xyzzy",
"number": 8888888888
},
{
"id": 3,
"user_id": 103,
"name":"sdfdsdv",
"number": 2222222222
}
]
Interface Class
public interface ApiInterface {
#GET("user/details”)
Call<List<User_List>> getUser(
#Query(“id”)String id
);
}
User_List Class
public class User_List {
#SerializedName("id")
#Expose
int id;
#SerializedName("user_id")
#Expose
int user_id;
#SerializedName("name")
#Expose
String name;
#SerializedName("number")
#Expose
Int number;
public int getId() {
return id;
}
public int getUser_id() {
return user_id;
}
public int getNumber() {
return number;
}
public String getName() {
return name;
}
}
MainActivity Class
Public void fetch() {
ApiInterface apiInterface = ApiClient.getRetrofit().create(ApiInterface.class);
Call<List<User_List>> user = apiInterface.getUser(id);
user(new Callback<List<user_List>>() {
#Override
public void onResponse(Call<List<user_List>> call, retrofit2.Response<List<user_List>> response) {
try{
if (response.isSuccessful()) {
for (int i = 0; i < user_list(); i++) {
int id = user_list.get(i).getId();
String name = user_list.get(i).getName();
}
}else {
}
}catch (Exception e){
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ArrayList<ProductEnquiry_Contributor>> call, Throwable t) {
}
});
}
I tried to parse it but can't find success,Can anyone suggest me how to parse this type of Response using Retrofit?
It gives me failure in response
Error: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
you can do this like this
#POST("endpoint)
Call<List<yourPOJO> methodname(#Body BodyPOJO bodyPojo);
or
#POST("endpoint)
Call<Response<List<yourPOJO>> methodname(#Body BodyPOJO bodyPojo);

Spring Boot Json Format

I want to create the Json Format as Shown below by using SpringBoot.
[
{
"name": "foo",
"albums": [
{
"title": "album_one",
"artist": "foo",
"ntracks": 12
},
{
"title": "album_two",
"artist": "foo",
"ntracks": 15
}
]
},
{
"name": "bar",
"albums": [
{
"title": "foo walks into a bar",
"artist": "bar",
"ntracks": 12
},
{
"title": "album_song",
"artist": "bar",
"ntracks": 17
}
]
}]
Please help me and please refer spring boot application which helps to create Json format as similar.
You don't need spring boot for this, you can do it using jackson.
You just need to define bean like:
public class ArtistInfo {
private String name;
private List<Album> albums;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Album> getAlbums() {
return albums;
}
public void setAlbums(List<Album> albums) {
this.albums = albums;
}
public static class Album {
private String title;
private String artist;
private int ntracks;
public Album(String title, String artist, int ntracks) {
super();
this.title = title;
this.artist = artist;
this.ntracks = ntracks;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public int getNtracks() {
return ntracks;
}
public void setNtracks(int ntracks) {
this.ntracks = ntracks;
}
}
}
Now you can use Jackson object mapper to produce JSON:
Initialize List of ArtistInfo
ObjectMapper mapper = new ObjectMapper();
List<ArtistInfo> artistInfos = initData();
String json = mapper.writeValueAsString(artistInfos);
System.out.println(json);
If you using this with Spring REST controller, spring will produce json if you return List of ArtistInfo

Expected BEGIN_OBJECT but was NUMBER at line 1 column 65 path $.data

I am trying to use Gson library to parse an api response. Here is the response String:
{
"data": {
"Thresh": {
"id": 412,
"title": "Zincirli Gardiyan",
"name": "Thresh",
"key": "Thresh"
},
"Aatrox": {
"id": 266,
"title": "Darkin Kılıcı",
"name": "Aatrox",
"key": "Aatrox"
},
"Tryndamere": {
"id": 23,
"title": "Barbar Kral",
"name": "Tryndamere",
"key": "Tryndamere"
},
"Gragas": {
"id": 79,
"title": "Kavgacı Ayyaş",
"name": "Gragas",
"key": "Gragas"
},
"Cassiopeia": {
"id": 69,
"title": "Yılanın Şefkati",
"name": "Cassiopeia",
"key": "Cassiopeia"
},
"type": "champion",
"version": "4.14.2"
}
}
Here are my classes:
public class Champion {
private int id;
private String title;
private String name;
private String key;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
and response class:
public class ChampionsResponse {
private String type;
private String version;
private Map<String, Map<String, Champion>> data;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public Map<String, Map<String, Champion>> getData() {
return data;
}
public void setData(Map<String, Map<String, Champion>> data) {
this.data = data;
}
}
I use the following line to use gson library:
Gson gson = new Gson();
try{
ChampionsResponse championsResponse = gson.fromJson(response, ChampionsResponse.class);
}catch(Exception e){
e.printStackTrace();
}
But i get the exception saying that "Expected BEGIN_OBJECT but was NUMBER at line 1 column 65 path $.data..". Can anyone tell me where i am mistaken?
Thanks
I found the problem, i need to use
private Map<String, Map<String, String>> data;
instead of
private Map<String, Map<String, Champion>> data;

Gson fromJson parsing nested json

{
"status_code": 200,
"status_text": "Success",
"count": 96,
"data": [
{
"model": "Spark",
"fuel_type": "",
"price": "352109",
"state": "",
"city": "Agartala",
"crawl_date": "2013-10-02 05:00:02",
"make": "Chevrolet",
"variant": "New Spark 1.0 BS4 OBDII"
},
{
"model": "Spark",
"fuel_type": "",
"price": "378914",
"state": "",
"city": "Agartala",
"crawl_date": "2013-10-02 05:00:03",
"make": "Chevrolet",
"variant": "New Spark 1.0 LS BS4 OBDII"
}
]
}
Above is the JSON string.
The equivalent classes for the JSON object is as follows :
public class CarPriceResult {
private int status_code;
private String status_text;
private int count;
private List<CarData> CarData;
public CarPriceResult() {
super();
}
public int getStatus_code() {
return status_code;
}
public void setStatus_code(int status_code) {
this.status_code = status_code;
}
public String getStatus_text() {
return status_text;
}
public void setStatus_text(String status_text) {
this.status_text = status_text;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public List<CarData> getCarData() {
return this.CarData;
}
public void setCarData(List<CarData> carData) {
this.CarData = carData;
}
public static class CarData {
private String model;
private String fuel_type;
private String state;
private String city;
private String crawl_date;
private String make;
private String variant;
public String getModel() {
return model;
}
public CarData() {
super();
}
public void setModel(String model) {
this.model = model;
}
public String getFuel_type() {
return fuel_type;
}
public void setFuel_type(String fuel_type) {
this.fuel_type = fuel_type;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCrawl_date() {
return crawl_date;
}
public void setCrawl_date(String crawl_date) {
this.crawl_date = crawl_date;
}
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getVariant() {
return variant;
}
public void setVariant(String variant) {
this.variant = variant;
}
}
}
The code to convert JSON to Java using Gson is as follows :
CarPriceResult cpr;
List<CarData> cd;
cpr = gson.fromJson(inputLine, CarPriceResult.class);
cd = cpr.getCarData();
object "cd" returns null and hence NPE is thrown.
what am I doing wrong?
Problem is in inputLine.
This code works well
String str = "{ \"status_code\": 200, \"status_text\": \"Success\", \"count\": 96, \"data\": [ { \"model\": \"Spark\",\"fuel_type\": \"\", \"price\": \"352109\", \"state\": \"\", \"city\": \"Agartala\", \"crawl_date\": \"2013-10-02 05:00:02\", \"make\": \"Chevrolet\", \"variant\": \"New Spark 1.0 BS4 OBDII\" }, { \"model\": \"Spark\", \"fuel_type\": \"\", \"price\": \"378914\", \"state\": \"\", \"city\": \"Agartala\", \"crawl_date\": \"2013-10-02 05:00:03\", \"make\": \"Chevrolet\", \"variant\": \"New Spark 1.0 LS BS4 OBDII\" } ] }";
CarPriceResult cpr = new Gson().fromJson(str, CarPriceResult.class);
List<CarData> cd = cpr.getCarData();
EDIT:
Also, your json does not correspond to class mapping
Json:
"data": [
class CarPriceResult
private List<CarData> CarData;
You should rename field to data or change key in json to CarData.
e.g.
Json:
"data": [
class CarPriceResult
private List<CarData> data;