I use Retrofit 2.4 and try to get data from Asp.Net Core 2.0 WebApi Service.
Here Java class:
public class Category {
private int CategoryID;
private String Name;
private String Image;
public Category(){
Name="";
Image="";
}
public Category(int categoryID, String name, String image) {
Name = name;
Image = image;
CategoryID=categoryID;
}
public int getCategoryID() {return CategoryID;}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getImage() {
return Image;
}
public void setImage(String image) {
Image = image;
}
}
Here Retrofit code:
public class Common {
public static User CURRENT_USER;
public static String SERVER_NAME="http://ip_address:5000";
public static IApiService ApiService;
public Common()
{
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(SERVER_NAME)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiService = retrofit.create(IApiService.class);
}
}
public interface IApiService
{
#GET("api/Categories")
Call<List<Category>> GetCategoryColl();
}
And then i write server side via Asp.Net Core 2.0 WebApi.
I have a controller:
[Produces("application/json")]
[Route("api/Categories")]
public class CategoriesController : Controller
{
private readonly MovieAppServerContext _context;
public CategoriesController(MovieAppServerContext context)
{
_context = context;
}
// GET: api/Categories
[HttpGet]
public IEnumerable<Category> GetCategory()
{
return _context.Category;
}
// GET: api/Categories/5
[HttpGet("{id}")]
public async Task<IActionResult> GetCategory([FromRoute] int id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var category = await _context.Category.SingleOrDefaultAsync(m => m.CategoryID == id);
if (category == null)
{
return NotFound();
}
return Ok(category);
}
// PUT: api/Categories/5
[HttpPut("{id}")]
public async Task<IActionResult> PutCategory([FromRoute] int id, [FromBody] Category category)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != category.CategoryID)
{
return BadRequest();
}
_context.Entry(category).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!CategoryExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// POST: api/Categories
[HttpPost]
public async Task<IActionResult> PostCategory([FromBody] Category category)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.Category.Add(category);
//await _context.SaveChangesAsync();
_context.SaveChanges();
return Ok(category);
}
// DELETE: api/Categories/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteCategory([FromRoute] int id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var category = await _context.Category.SingleOrDefaultAsync(m => m.CategoryID == id);
if (category == null)
{
return NotFound();
}
_context.Category.Remove(category);
// await _context.SaveChangesAsync();
_context.SaveChanges();
return Ok("Removed!");
}
private bool CategoryExists(int id)
{
return _context.Category.Any(e => e.CategoryID == id);
}
}
Here server side class of Category:
public class Category
{
[Key]
public int CategoryID { get; set; }
public String Name { get; set; }
public String Image { get; set; }
public Category()
{
}
public Category(String name, String image)
{
Name = name;
Image = image;
}
}
So, i check server code via Swagger and it works well: i get all data from Categories List.
But, when i try to get data from Android code via Retrofit - i get collection with empty objects : all fields are null or empty (i think it is default values).
So, here the code:
public class Home extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
List<Category> _categoryList =new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
//some code
Common.ApiService.GetCategoryColl().enqueue(new Callback<List<Category>>() {
#Override
public void onResponse(Call<List<Category>> call, Response<List<Category>> response) {
Log.i("GetCategories",response.message());
_categoryList=response.body();
// !!!! HERE. _category list contains objects but all of them
// are empty!
}
#Override
public void onFailure(Call<List<Category>> call, Throwable t) {
Log.e("GetCategories",t.getMessage());
}
});
}
}
So, i do not know, why it happens? How to fix that?
Thank you!
You haven't added #SerializedName("json-key-name") to your fields in the Java Category class:
#SerializedName("categoryId")
private int CategoryID;
#SerializedName("name")
private String Name;
#SerializedName("image")
private String Image;
Now GSON can map JSON response to the POJO properly.
By default Gson expects the field names to be the same as the Json ones, if you want to change this behavior, you have two options:
1.Use a FieldNamingPolicy, for your case it would be UPPER_CAMEL_CASE, below a sample how to do it for Retrofit:
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(SERVER_NAME)
.addConverterFactory(GsonConverterFactory.create())
.build();
2. Use the SerializedName annotation on your java fields.
Related
I am new to Spring boot, and was trying to create a post api to post the following json to.
However, when I do a get on the api, for the nested elements, null values are displayed.
Json Request:
{
"messageType": "abcd",
"messageVersion": "1.1.0",
"p_messageVersion": "1.095",
"acsTransID": "6834628",
"p_formValues_BRW": {
"action": "http://10.10.65.96:8080/CORE/Test.htm",
"correctFormData": "1234",
"incorrectFormData": "0000",
"cancelFormData": "true"
}
}
Response on Doing a Get:
[{"acsTransID":"6834628","p_messageVersion":"1.095","messageVersion":"1.1.0","messageType":"abcd","p_formValues_BRW":{"action":null,"correctFormData":null,"incorrectFormData":null,"cancelFormData":null}}]
My Model Object
public class Product {
#JsonProperty("acsTransID")
private String acsTransID;
#JsonProperty("p_messageVersion")
private String p_messageVersion;
#JsonProperty("messageVersion")
private String messageVersion;
#JsonProperty("messageType")
private String messageType;
#JsonProperty("p_formValues_BRW")
private p_formValues_BRW p_formValues_BRW;
public Product(p_formValues_BRW p_formValues_BRW) {
this.p_formValues_BRW=p_formValues_BRW;
}
public Product() {
}
public String getacsTransID() {
return acsTransID;
}
public void setacsTransID(String acsTransID) {
this.acsTransID = acsTransID;
}
public String getp_messageVersion() {
return p_messageVersion;
}
public void setp_messageVersion(String p_messageVersion) {
this.p_messageVersion = p_messageVersion;
}
public String getmessageVersion() {
return messageVersion;
}
public void setmessageVersion(String messageVersion) {
this.messageVersion = messageVersion;
}
public String getmessageType() {
return messageType;
}
public void setmessageType(String messageType) {
this.messageType = messageType;
}
public p_formValues_BRW getp_formValues_BRW() {
return p_formValues_BRW;
}
public void setp_formValues_BRW(p_formValues_BRW p_formValues_BRW) {
this.p_formValues_BRW = p_formValues_BRW;
}
/*
public Product withPFormValuesBRW(PFormValuesBRW pFormValuesBRW) {
this.pFormValuesBRW = pFormValuesBRW;
return this;
}*/
}
class p_formValues_BRW {
#JsonProperty("action")
private String action;
#JsonProperty("correctFormData")
private String correctFormData;
#JsonProperty("incorrectFormData")
private String incorrectFormData;
#JsonProperty("cancelFormData")
private String cancelFormData;
public String getaction() {
return action;
}
public void setaction(String action) {
this.action = action;
}
public String getcorrectFormData() {
return correctFormData;
}
public void setcorrectFormData(String correctFormData) {
this.correctFormData = correctFormData;
}
public String getincorrectFormData() {
return incorrectFormData;
}
public void setincorrectFormData(String incorrectFormData) {
this.incorrectFormData = incorrectFormData;
}
public String getcancelFormData() {
return cancelFormData;
}
public void setcancelFormData(String cancelFormData) {
this.cancelFormData = cancelFormData;
}
}
My Controller
#RestController
public class ProductServiceController {
private static Map<String, Product> productRepo = new HashMap<>();
#RequestMapping(value = "/products", method = RequestMethod.POST)
public ResponseEntity<Object> createProduct(#RequestBody Product product, p_formValues_BRW p_formValues_BRW) {
product.setp_formValues_BRW(p_formValues_BRW);
productRepo.put(product.getacsTransID(), product);
// productRepo.put(product., PFormValuesBRWRepo);
return new ResponseEntity<>("Product is created successfully", HttpStatus.CREATED);
}
#RequestMapping(value = "/products")
public ResponseEntity<Object> getProduct() {
return new ResponseEntity<>(productRepo.values(), HttpStatus.OK);
}
}
What I am doing wrong. Also, would it be better to use JPARepositories and #autowired.
You don't need to add p_formValues_BRW in createProduct() function's parameter separately, because on your JSON Request you pass p_formValues_BRW as nested object.
So on your controller when you hit "/products" you will get p_formValues_BRW in Product, so function after changes look like this:
#RequestMapping(value = "/products", method = RequestMethod.POST)
public ResponseEntity<Object> createProduct(#RequestBody Product product) {
product.setp_formValues_BRW(product.getp_formValues_BRW());
productRepo.put(product.getacsTransID(), product);
// productRepo.put(product., PFormValuesBRWRepo);
return new ResponseEntity<>("Product is created successfully", HttpStatus.CREATED);
}
As you already giving p_formValues_BRW in request body, you need not add it in Product.
#RequestMapping(value = "/products", method = RequestMethod.POST)
public ResponseEntity<Object> createProduct(#RequestBody Product product) {
productRepo.put(product.getacsTransID(), product);
// productRepo.put(product., PFormValuesBRWRepo);
return new ResponseEntity<>("Product is created successfully", HttpStatus.CREATED);
}
When I use a distance API I get this response:
<?xml version="1.0" encoding="utf-8"?>
<Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/search/local/ws/rest/v1">
<Copyright>Copyright © 2020 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.</Copyright>
<BrandLogoUri>http://dev.virtualearth.net/Branding/logo_powered_by.png</BrandLogoUri>
<StatusCode>200</StatusCode>
<StatusDescription>OK</StatusDescription>
<AuthenticationResultCode>ValidCredentials</AuthenticationResultCode>
<TraceId>df8ee9b6422846f0b97644c0a631deb8|DU00000D71|0.0.0.0|DU000005EC, DU00000480|Ref A: F00DC0285E97417B99490A8C98E65E31 Ref B: DB3EDGE1608 Ref C: 2020-06-09T18:53:54Z|Ref A: 69E0F633DF6448A89B2B904773DF19AB Ref B: DB3EDGE0807 Ref C: 2020-06-09T18:53:54Z</TraceId>
<ResourceSets>
<ResourceSet>
<EstimatedTotal>1</EstimatedTotal>
<Resources>
<Route>
<Id>v69,h1509963868,i0,a2,cen-US,dAAAAAAAAAAA1,y0,s1,m1,o1,t4,wWriswmZmQkBa9bnail0kQA2~BFnWzEBwiKgBBH_gASHtAT8A0~VHVuaXMsIFR1bmlzaWE1~~~~v11,w-Ki_XmFfQUC94xQdyYUlQA2~BFnWzEBYRLoBBH_gAc1znT4B0~U2ZheCwgVHVuaXNpYQ2~~~~v11,k1</Id>
<BoundingBox>
<SouthLatitude>34.74499</SouthLatitude>
<WestLongitude>10.18235</WestLongitude>
<NorthLatitude>36.800014</NorthLatitude>
<EastLongitude>10.76493</EastLongitude>
</BoundingBox>
<DistanceUnit>Kilometer</DistanceUnit>
<DurationUnit>Second</DurationUnit>
<TravelDistance>271.101</TravelDistance>
...
I want to get the value of TravelDistance.
If possible a full code because I have been trying with this for long time and no solution.
You can use XmlMapper of jackson to de/serialize your XML.
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.8</version>
</dependency>
so you shall need to create an instance of it and deserialize as follows :
XmlMapper mapper = new XmlMapper();
Response value = xmlMapper.readValue("<Response>..</Response>", Response.class);
So you will need to create your object model that reflects your XML.
public class Response {
private String Copyright;
private String BrandLogoUri;
private String StatusCode;
private String StatusDescription;
private String AuthenticationResultCode;
private String TraceId;
ResourceSets ResourceSetsObject;
// Getter Methods
public String getCopyright() {
return Copyright;
}
public String getBrandLogoUri() {
return BrandLogoUri;
}
public String getStatusCode() {
return StatusCode;
}
public String getStatusDescription() {
return StatusDescription;
}
public String getAuthenticationResultCode() {
return AuthenticationResultCode;
}
public String getTraceId() {
return TraceId;
}
public ResourceSets getResourceSets() {
return ResourceSetsObject;
}
// Setter Methods
public void setCopyright(String Copyright) {
this.Copyright = Copyright;
}
public void setBrandLogoUri(String BrandLogoUri) {
this.BrandLogoUri = BrandLogoUri;
}
public void setStatusCode(String StatusCode) {
this.StatusCode = StatusCode;
}
public void setStatusDescription(String StatusDescription) {
this.StatusDescription = StatusDescription;
}
public void setAuthenticationResultCode(String AuthenticationResultCode) {
this.AuthenticationResultCode = AuthenticationResultCode;
}
public void setTraceId(String TraceId) {
this.TraceId = TraceId;
}
public void setResourceSets(ResourceSets ResourceSetsObject) {
this.ResourceSetsObject = ResourceSetsObject;
}
}
public class ResourceSets {
ResourceSet ResourceSetObject;
// Getter Methods
public ResourceSet getResourceSet() {
return ResourceSetObject;
}
// Setter Methods
public void setResourceSet(ResourceSet ResourceSetObject) {
this.ResourceSetObject = ResourceSetObject;
}
}
public class ResourceSet {
private String EstimatedTotal;
Resources ResourcesObject;
// Getter Methods
public String getEstimatedTotal() {
return EstimatedTotal;
}
public Resources getResources() {
return ResourcesObject;
}
// Setter Methods
public void setEstimatedTotal(String EstimatedTotal) {
this.EstimatedTotal = EstimatedTotal;
}
public void setResources(Resources ResourcesObject) {
this.ResourcesObject = ResourcesObject;
}
}
public class Resources {
Route RouteObject;
// Getter Methods
public Route getRoute() {
return RouteObject;
}
// Setter Methods
public void setRoute(Route RouteObject) {
this.RouteObject = RouteObject;
}
}
public class Route {
private String Id;
BoundingBox BoundingBoxObject;
private String DistanceUnit;
private String DurationUnit;
private String TravelDistance;
// Getter Methods
public String getId() {
return Id;
}
public BoundingBox getBoundingBox() {
return BoundingBoxObject;
}
public String getDistanceUnit() {
return DistanceUnit;
}
public String getDurationUnit() {
return DurationUnit;
}
public String getTravelDistance() {
return TravelDistance;
}
// Setter Methods
public void setId(String Id) {
this.Id = Id;
}
public void setBoundingBox(BoundingBox BoundingBoxObject) {
this.BoundingBoxObject = BoundingBoxObject;
}
public void setDistanceUnit(String DistanceUnit) {
this.DistanceUnit = DistanceUnit;
}
public void setDurationUnit(String DurationUnit) {
this.DurationUnit = DurationUnit;
}
public void setTravelDistance(String TravelDistance) {
this.TravelDistance = TravelDistance;
}
}
public class BoundingBox {
private String SouthLatitude;
private String WestLongitude;
private String NorthLatitude;
private String EastLongitude;
// Getter Methods
public String getSouthLatitude() {
return SouthLatitude;
}
public String getWestLongitude() {
return WestLongitude;
}
public String getNorthLatitude() {
return NorthLatitude;
}
public String getEastLongitude() {
return EastLongitude;
}
// Setter Methods
public void setSouthLatitude(String SouthLatitude) {
this.SouthLatitude = SouthLatitude;
}
public void setWestLongitude(String WestLongitude) {
this.WestLongitude = WestLongitude;
}
public void setNorthLatitude(String NorthLatitude) {
this.NorthLatitude = NorthLatitude;
}
public void setEastLongitude(String EastLongitude) {
this.EastLongitude = EastLongitude;
}
}
I'm trying to get the parameters inside jSon items>item>image>images>transparent using the Gson library. The idea is to capture transparent, transparent_blank and transparent_dark. But I don't know how I can get these values, for the moment I have created the following:
Json
{
"date_layout":"day-month-year",
"lastupdate":1547596830,
"items":[{
"name":"Cleans Cuts",
"featured":"true",
"item":{
"image":"http:www.domain.com/unwanted_image.jpg",
"images":{
"transparent":"http:www.domain.com/desired_image1.jpg",
"transparent_blank":"http:www.domain.com/desired_image2.jpg",
"transparent_dark":"http:www.domain.com/desired_image3.jpg"
}
}
},
{
"name":"Cleans Cuts",
"featured":"true",
"item":{
"image":"http:www.domain.com/unwanted_image.jpg",
"images":{
"transparent":"http:www.domain.com/desired_image1.jpg",
"transparent_blank":"http:www.domain.com/desired_image2.jpg",
"transparent_dark":"http:www.domain.com/desired_image3.jpg"
}
}
}]
}
.MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String url = "http://www.example.com/file.json";
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
if(response.isSuccessful()){
String response_jSon = response.body().string();
Gson gson = new Gson();
Datos datosFinal = gson.fromJson(response_jSon, Datos.class);
for (int i=0; i<datosFinal.items.size(); i++){
Log.d("msg_2", datosFinal.items.get(i).name);
}
}
And I'm only able to get to items as you can see in the .MainActivity Log.
Class Objects for the Json
Datos.java
public class Datos {
public String date_layout;
public Int lastupdate;
List<items> items;
}
items.java
public class items {
public String name;
}
The json is not very clean, I would suggest that you rework how this json string is generated, but if you still want to achieve getting those values without reworking the json, you need to change your Items class to :
`public class items {
public String name;
public String featured;
public Item item;
}`
Then you need to create another class called Item
`public class Item{
public String image;
public Image images;
}`
You will also need to create an Image class, like so:
`public class Image {
public String transparent;
public String transparent_blank;
public String transparent_dark;
}`
Then you can log these values in your loop:
`Datos datosFinal = gson.fromJson(response_jSon, Datos.class);
for (int i=0; i<datosFinal.items.size(); i++){
Log.d("msg_2", datosFinal.items.get(i).item.images.transparent);
Log.d("msg_2", datosFinal.items.get(i).item.images.transparent_blank);
Log.d("msg_2", datosFinal.items.get(i).item.images.transparent_dark);
}`
While this may work, I would highly suggest you to rework your json and make it easier to maintain.
You have to create the following class also to getting value for transparent, transparent_blank and transparent_dark
Images.java
Item.java
Replace this class:
public class Items{
private Item item;
private String name;
private String featured;
public Item getItem ()
{
return item;
}
public void setItem (Item item)
{
this.item = item;
}
public String getName ()
{
return name;
}
public void setName (String name)
{
this.name = name;
}
public String getFeatured ()
{
return featured;
}
public void setFeatured (String featured)
{
this.featured = featured;
}
}
Add this class:
public class Images{
private String transparent_blank;
private String transparent_dark;
private String transparent;
public String getTransparent_blank ()
{
return transparent_blank;
}
public void setTransparent_blank (String transparent_blank)
{
this.transparent_blank = transparent_blank;
}
public String getTransparent_dark ()
{
return transparent_dark;
}
public void setTransparent_dark (String transparent_dark)
{
this.transparent_dark = transparent_dark;
}
public String getTransparent ()
{
return transparent;
}
public void setTransparent (String transparent)
{
this.transparent = transparent;
}
}
Also, Add this Class:
public class Item {
private Images images;
private String image;
public Images getImages ()
{
return images;
}
public void setImages (Images images)
{
this.images = images;
}
public String getImage ()
{
return image;
}
public void setImage (String image)
{
this.image = image;
}
}
Now, you will get the value using the getter method.
you must use
public class items {
public String name;
#Expose(serialize = false, deserialize = false)
public String featured;
#Expose(serialize = false, deserialize = false)
public item mItem;
}
public class item {
#Expose(serialize = false, deserialize = false)
public String image;
#Expose(serialize = false, deserialize = false)
public images mImages;
}
public class images {
#Expose(serialize = false, deserialize = false)
public String transparent;
#Expose(serialize = false, deserialize = false)
public String transparent_blank;
#Expose(serialize = false, deserialize = false)
public String transparent_dark;
}
you can genetate pojo by using http://www.jsonschema2pojo.org/
I'm using retrofit to send a call to an api to post an issue in a bug-tracker through my android app. The API needs it formatted a specific way, so I created a custom object to pass as a parameter. Unfortunately when I'm sending the request to the API its formatting it incorrectly. It alphabetizes the parameters, puts quotes around both the keys and the values, and adds an # to the beginning of my data, leading the API to not be able to make sense of what I'm trying to post. The format I'm looking to send is:
{ fb_user_id: dummyUID,
email: dummy#email.com,
first_name: John,
last_name: Smith,
project: android,
type: bug,
subject: title,
description: description }
Instead of the above, my api is receiving the data as
#"description":"description",
"email":"dummy#email.com",
"fb_user_id":"dummyUID",
"first_name":"John",
"last_name":"Smith",
"project":"android",
"subject":"title",
"type":"bug"
I'm using retrofit to do so, with my interface looking like
public interface MyAPI {
#POST("/op_create_ticket")
Observable<JsonElement> createTicket(#Body Ticket ticket);
}
And my activity calling it looking like:
public class HelpActivity extends BaseActivity {
#BindView(R.id.textView)
TextView textView;
#BindView(R.id.spinner)
Spinner spinner;
#BindView(R.id.email)
EditText email;
#BindView(R.id.firstName)
EditText firstName;
#BindView(R.id.lastName)
EditText lastName;
#BindView(R.id.subject)
EditText title;
#BindView(R.id.description)
EditText description;
#BindView(R.id.button3)
Button button3;
FirebaseAuth fbauth = FirebaseAuth.getInstance();
FirebaseUser user = fbauth.getCurrentUser();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_help);
ButterKnife.bind(this);
}
#OnClick(R.id.button3)
public void onViewClicked() {
final GsonBuilder gsonBuilder = new GsonBuilder();
final Gson gson = gsonBuilder.create();
Retrofit.Builder builder = new Retrofit.Builder();
builder.baseUrl("https://my.url");
builder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
builder.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
MyAPI api = retrofit.create(TriggerWatchAPI.class);
Ticket ticket = new Ticket();
ticket.setFb_user_id(user.getUid());
ticket.setEmail(email.getText().toString());
ticket.setFirst_name(firstName.getText().toString());
ticket.setLast_name(lastName.getText().toString());
ticket.setProject("android");
ticket.setType("design");
ticket.setSubject(title.getText().toString());
ticket.setDescription(description.getText().toString());
api.createTicket(ticket).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<JsonElement>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(JsonElement jsonElement) {
Log.d(getTag(), "zzzOnNext");
}
#Override
public void onError(Throwable e) {
Log.e(getTag(), "err", e);
}
#Override
public void onComplete() {
}
});
}
}
I'm wondering if there's any kind of converter or something that can convert my object to the kind of data the API is looking for.
edit: forgot to add my custom pojo
package watch.trigger.Model;
public class Ticket {
private String project;
private String first_name;
private String email;
private String description;
private String subject;
private String last_name;
private String fb_user_id;
private String type;
public String getProject ()
{
return project;
}
public void setProject (String project)
{
this.project = project;
}
public String getFirst_name ()
{
return first_name;
}
public void setFirst_name (String first_name)
{
this.first_name = first_name;
}
public String getEmail ()
{
return email;
}
public void setEmail (String email)
{
this.email = email;
}
public String getDescription ()
{
return description;
}
public void setDescription (String description)
{
this.description = description;
}
public String getSubject ()
{
return subject;
}
public void setSubject (String subject)
{
this.subject = subject;
}
public String getLast_name ()
{
return last_name;
}
public void setLast_name (String last_name)
{
this.last_name = last_name;
}
public String getFb_user_id ()
{
return fb_user_id;
}
public void setFb_user_id (String fb_user_id)
{
this.fb_user_id = fb_user_id;
}
public String getType ()
{
return type;
}
public void setType (String type)
{
this.type = type;
}
#Override
public String toString()
{
return "ClassPojo [project = "+project+", first_name = "+first_name+", email = "+email+", description = "+description+", subject = "+subject+", last_name = "+last_name+", fb_user_id = "+fb_user_id+", type = "+type+"]";
}
}
don't send a custom object, send a JSON object as a String and in the API receive it as a JSON object.
first add this in your gradle:
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
1- change this
public interface MyAPI {
#Headers("Content-Type: application/json")
#POST("/op_create_ticket")
Observable<JsonElement> createTicket(#Body Ticket ticket);
}
to :
public interface MyAPI {
#POST("/op_create_ticket")
Observable<String> createTicket(#Body String ticket);
}
2- change this
Ticket ticket = new Ticket();
ticket.setFb_user_id(user.getUid());
ticket.setEmail(email.getText().toString());
ticket.setFirst_name(firstName.getText().toString());
ticket.setLast_name(lastName.getText().toString());
ticket.setProject("android");
ticket.setType("design");
ticket.setSubject(title.getText().toString());
ticket.setDescription(description.getText().toString());
api.createTicket(ticket).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<JsonElement>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(JsonElement jsonElement) {
Log.d(getTag(), "zzzOnNext");
}
#Override
public void onError(Throwable e) {
Log.e(getTag(), "err", e);
}
#Override
public void onComplete() {
}
});
to
JSONObject tickenJson= new JSONObject();
Ticket ticket = new Ticket();
ticket.setFb_user_id(user.getUid());
ticket.setEmail(email.getText().toString());
ticket.setFirst_name(firstName.getText().toString());
ticket.setLast_name(lastName.getText().toString());
ticket.setProject("android");
ticket.setType("design");
ticket.setSubject(title.getText().toString());
ticket.setDescription(description.getText().toString());
ticketJson.put("fb_user_id",user.getUid());
ticketJson.put("email",email.getText().toString());
ticketJson.put("first_name",firstName.getText().toString());
ticketJson.put("last_name",lastName.getText().toString());
ticketJson.put("project","android");
ticketJson.put("type","design");
ticketJson.put("type",title.getText().toString());
ticketJson.put("description",description.getText().toString());
api.createTicket(ticketJson.toString()).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<JsonElement>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(JsonElement jsonElement) {
Log.d(getTag(), "zzzOnNext");
}
#Override
public void onError(Throwable e) {
Log.e(getTag(), "err", e);
}
#Override
public void onComplete() {
}
});
I'm new to Retrofit and JSON and I don't really know how to parse the next json string:
{
"weight":[
{ "bmi":21,
"date":"2016-12-09",
"fat":14.059000015258789,
"logId":1222222222222,
"source":"Aria",
"time":"11:58:24",
"weight":68
},
{ "bmi":21.83,
"date":"2016-12-14",
"logId":1222222222223,
"source":"Aria",
"time":"14:31:39",
"weight":70.7
}
]
}
I just want "weight" and "date" inside weight array. I've created a pojo class following some examples but it's not working.
Also when trying it with my pojo class I couldn't get "weight" as a string (I'll then use it as a double) using .string().
(I know using .toString() shows something like "com.myPackage.MyPojo#xxxx").
For now, I have only been able to get the whole json through ResponseBody:
Call<ResponseBody>call = repository.getFitbitApi().getData();
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
What am I doing wrong? Here are my pojo classes, just an attempt...:
public class WeightList {
#SerializedName("weight")
#Expose
private ArrayList<WeightLogFitbit> weight = new ArrayList<>();
public WeightList(){
}
public ArrayList<WeightLogFitbit> getWeight() {
return weight;
}
public void setWeight(ArrayList<WeightLogFitbit> weight) {
this.weight = weight;
}
}
And:
public class WeightLogFitbit {
//Variables in my JSON
#SerializedName("bmi")
#Expose
private String bmi;
#SerializedName("date")
#Expose
private String date;
#SerializedName("logId")
#Expose
private String logId;
#SerializedName("source")
#Expose
private String source;
#SerializedName("time")
#Expose
private String time;
#SerializedName("weight")
#Expose
private double weight;
#SerializedName("fat")
#Expose
private String fat;
public WeightLogFitbit(){}
//Getters and setters
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getBmi(){
return bmi;
}
public void setBmi(String bmi) {
this.bmi = bmi;
}
//
public String getFat(){
return fat;
}
public void setFat(String fat) {
this.fat = fat;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getLogId() {
return logId;
}
public void setLogId(String logId) {
this.logId = logId;
}
}
NOTE: I'm using RxSocialConnect library, which implements RxJava, Retrofit 2, OkHttp3 and gson, just in case. I did this following this example.
Rest of classes I'm using:
public class FitbitBtnActivity extends AppCompatActivity {
private FitbitRepository repository;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fitbit_btn);
repository = new FitbitRepository();
setUpFitbit();
}
private void setUpFitbit() {
findViewById(R.id.fitbitbtn).setOnClickListener(v ->
RxSocialConnect.with(this, repository.fitbitService())
.subscribe(response -> response.targetUI().showToken(response.token()),
error -> showError(error))
);
findViewById(R.id.retrievebtn).setOnClickListener(v -> {
Call<ResponseBody>call = repository.getFitbitApi().getData();
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
//Original code from example in RxSocialConnect
/*.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Object>() {
#Override
public void call(Object user) {
FitbitBtnActivity.this.showUserProfile(user.toString());
}
},
error -> FitbitBtnActivity.this.showError(error));*/
}
);
}
And:
public class FitbitRepository {
private final FitbitApiRest fitbitApi;
public FitbitRepository() {
fitbitApi = initFitbitApiRest();
}
private FitbitApiRest initFitbitApiRest() {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new OAuth2Interceptor(FitbitApi20.class))
.build();
return new Retrofit.Builder()
.baseUrl(FitbitApiRest.URL_BASE)
.client(client)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(FitbitApiRest.class);
}
FitbitApiRest getFitbitApi() {
return fitbitApi;
}
interface FitbitApiRest {
String URL_BASE = "https://api.fitbit.com";
#GET("myrequest.json")
Call<ResponseBody> getData();
}
OAuth20Service fitbitService() {
final String client_id = "xxxxx";
final String client_secret = "1xxxxxxxxxxxxxxxxxx";
final String redirect_uri = "http://example.com";
final String permissions = "weight";
return new ServiceBuilder()
.apiKey(client_id)
.apiSecret(client_secret)
.callback(redirect_uri)
.scope(permissions)
.build(FitbitApi20.instance());
}
}
You need to add this to your dependencies:
compile 'com.squareup.retrofit2:converter-gson:your-version'
and then add a gson converter to your Retrofit instance like this:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
and change your call in the api to return WeightList:
Call<WeightList> getData();