0

Response from a client (rest call) has a json element like USERId. The related java variable is as below

@JsonProperty("USERId")
private String uSERId;

I am using spring RestTemplate to make this rest call and for mapping from JSON to JAVA I am using GSON. I have completely excluded jackson databind which is spring rest template's default mapper like below.

this.getMessageConverters().removeIf(converter -> converter.getClass().getName().equals(MappingJackson2HttpMessageConverter.class.getName()));
GsonHttpMessageConverter messageConverter = new GsonHttpMessageConverter();
messageConverter.setGson(gson);
this.getMessageConverters().add(messageConverter);

This way, I made sure only GSON is used for mapping.

When I directly hit client rest service on postman, I see this filed has a value - "USERId": "025076373". However the response object from RestTemplate doesnt have this field i.e., all other fields with proper java canonical naming are mapped properly. I mean all other fields in the respone object are mapped with values from response json. Response object doesnt have uSERId or the corresponding value.

I believe this issue is probably because of the weird naming convention, however the same works fine with MappingJackson2HttpMessageConverter.

I have tried debugging by writing an adapter and assigning it to gsonBuilder and then setting that to GsonHttpMessageConverter.

gsonBuilder.registerTypeHierarchyAdapter(String.class, new StringTypeAdapter().nullSafe())

While debugging the adapter, I could see all other fields except USERId.

Object mapper of jackson databind has a property MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, which I believe is the reason why the same field is working jackson. I couldnt find a similar property with GSON. Any pointers on how to fix this issue would be very helpful.

Technologies used : spring boot spring rest template com.google.code.gson:gson:2.8.6

1 Answers1

0

Try replacing @JsonProperty annotation with this @SerializedName.

Example:

import com.google.gson.annotations.SerializedName;

public class Foo {    
   @SerializedName("USERId")
   private String uSERId;
}

Edit:

The second option is to use custom JsonDeserializer. Here is an example:

public class UserDeserializer implements JsonDeserializer<User> {

    @Override
    public User deserialize(JsonElement paramJsonElement, Type paramType,
            JsonDeserializationContext paramJsonDeserializationContext) throws JsonParseException {

    User user = new Gson().fromJson(paramJsonElement.getAsJsonObject(), User.class);

    try {
        String id = null;
        if (paramJsonElement.getAsJsonObject().get("USERId") != null) {
            id = paramJsonElement.getAsJsonObject().get("USERId").getAsString();
        }

        user.setuSERId(id);
    } catch (IllegalArgumentException e) {
        throw new RuntimeException(e);
    }

    return user;
}

Then create your own Gson like this:

Gson customGson = new GsonBuilder()
                .registerTypeAdapter(User.class, new UserDeserializer())
                .create();

And set it on your converter:

messageConverter.setGson(customGson);
Iske
  • 1,150
  • 9
  • 18
  • This field is from a client jar, and since it is working with jackson, they are not willing to update their objects. – Rama Krishna Raju GVSS Jul 02 '20 at 08:55
  • Hi Iske, I have tried adding deserializer to the converter while debugging this however I dont see a json element named USERId. I see all other fields coming with variable name and values execpt this field. My guess, gson was not able to read this element because of the weird naming convention. Found the following URL while searchign on google. https://stackoverflow.com/questions/6332651/gson-how-to-get-a-case-insensitive-element-from-json Appreciate your help. – Rama Krishna Raju GVSS Jul 06 '20 at 11:45