question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

@SerializedName bug in Java when it's used with Retrofit2 library

See original GitHub issue

Gson version

2.9.0

Java / Android version

java 17

Used tools

-Maven wrapper 3.8.4

Description

@SerializedName is not properly serialized in object.The deserialization from URL json to object is ok but not the serialization. If i use @JsonProperty the name is correctly serialized.

Expected behavior

I expect the SerializedName should be used which is “bookNameTest” when I get the return Object but it’s not, it’s only printed out correctly in the std but if you get the object as return, the response is not correct @SerializedName(“bookNameTest”) private String bookName;

Actual behavior

{ retrofit2.Response<Book> response = bookClient.getBook(“api/v1/bookService/otherBooks”).execute(); return response.body(); }

=> Wrong behavior here, i expect “bookNameTest”: “JWT” but it’s printed “bookName”=“JWT”

{
    "bookId": 1,
    "price": 22.25,
    "bookName": "JWT"
}

Reproduction steps

  1. Create class Book.java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
    private int bookId;
    private double price;

    @SerializedName("bookNameTest")
    private String bookName;
}
  1. Create a GET API
@GetMapping(value = "/bookService/otherBooks", produces = MediaType.APPLICATION_JSON_VALUE)
      public Book getOtherBook(@RequestParam(required = false) String bookID) throws IOException {
      retrofit2.Response<Book> response = bookClient.getBook("api/v1/bookService/otherBooks").execute();
      Gson gson = new GsonBuilder().setPrettyPrinting().create();
      String jsonString = gson.toJson(response.body());
      System.out.println(jsonString);
      System.out.println(response.body());
      return response.body();
}

The mock Json response from URL endpoint “api/v1/bookService/otherBooks”

{
    "bookId": 1,
    "price": 22.25,
    "bookNameTest": "JWT"
}

Please note for bookClient I used Retrofit and use Gson converter. And then the deserialization is correctly done but after that the serialization to use the @SerializedName is not correct.

public bookClient bookClient(){
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .build();

        return new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl("/") //can use localhost
                .client(okHttpClient)
                .build().create(bookClient.class);

I have checked the jsonString is printed out correctly from console using System.out.println(jsonString)

{
  "bookId": 1,
  "price": 22.25,
  "bookNameTest": "JWT"
}

but the return response.body() is not Book(bookId=1, price=22.25, bookName=JWT}

==================================================== If inside Book.java, i used @JsonProperty, the book can be deserialized and serialized correctly. With using the same code, the return object, it will use @JsonProperty name which is “bookNameTest”

import com.fasterxml.jackson.annotation.JsonProperty;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
    private int bookId;
    private double price;

    @JsonProperty("bookNameTest")
    private String bookName;
    private Author author;
    private Date publishedDate;
}

Correct output

{
    "bookId": 1,
    "price": 22.25,
    "bookNameTest": "JWT"
}

Exception stack trace

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
harrylhpcommented, Jun 28, 2022

Hi Marco, i have found the issue, it’s from SpringBoot configuration. I need to add a new config inside application.yml to force it to use Gson

spring
  mvc:
    converters:
      preferred-json-mapper: gson

Thank for your time. I think i’ll close the issue as it’s not a bug it’s SpringBoot configuration 😃

0reactions
harrylhpcommented, Jun 28, 2022

Hi Marco For me to force using Gson, i have defined the converter inside the Client before sending http Request and it’s using Gson. Else if i define to use .addConverterFactory(JacksonConverterFactory.create()), the Gson initialization will fail so i’m pretty sure my SpringBoot is using Gson at the time of converting.

public bookClient bookClient(){
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .build();

        return new Retrofit.Builder()
                .**addConverterFactory(GsonConverterFactory.create())**
                .baseUrl("/") //can use localhost
                .client(okHttpClient)
                .build().create(bookClient.class);

For Lombok, i have checked the generated classes toString for both @SerializedName and @JsonProperty i don’t see any dfiference. So it’s kind of confusing me for the Gson behavior, as you could see the Serialized String from println is correct, but if calling the response.body() to get Object, it’s not as I expected the library will behave

Read more comments on GitHub >

github_iconTop Results From Across the Web

Android : Issues with Retrofit 2 and GSON & JSON
This question cannot presently be edited, for this reason: "Links to ideone.com must be accompanied by code. · (To clarify, please add your...
Read more >
Consuming APIs with Retrofit | CodePath Android Cliffnotes
This library makes downloading JSON or XML data from a web API fairly straightforward. Once the data is downloaded then it is parsed...
Read more >
Retrofit Android Example Tutorial - DigitalOcean
Retrofit automatically serialises the JSON response using a POJO(Plain Old Java Object) which must be defined in advanced for the JSON Structure ...
Read more >
Retrofit 2 and the (Three) @Body problem | by abangkis p
First you can add a @SerializedName(“field_name”) for each field that you don't want to be obfuscate. Or you can do. To make short,...
Read more >
Manage REST API in Kotlin with Okhttp3, Retrofit2, Gson, and ...
We used Google GSON library to parse JSON to Kotlin data class. @SerializedName(“”) annotation. This is used when the property name in the ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found