简体   繁体   中英

Retrofit get object with empty fields

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM