Question

I am using Spring for Android to request data from my restful server and gson to Converter json to Java objetct without accessing any function in the object.
As there is a json property "user_id", what I want to save this as the primary key of the sqlite data after convertion.
The problem is my sqlite library defined a "mId" property as the primary key in abstract class.And gson convert is not using a "set function" to set the property. The only thing I want is turn user_id to mId properly.

Here is the code:
1. the abstract class to access sqlite:

public abstract class Model {
    protected Long mId = null;
    public final Long getId() {
        return mId;
    }

    public void setId(Long id){
        mId = id;
    }

    public void saveToSqlite(){
        //using mId;
    }
}

2.An class for restful user data:

public class User extends Model implements Serializable{
    private static final long serialVersionUID = 1L;
    @SerializedName("user_id")
    private Long userId;

    public Long getUserId() {
        return userId;
    }

    //this function is not accessed when user object generated
    public void setUserId(Long userId) {
        this.userId = userId;
        this.setId(userId);
    }
}

3.request and convert code:

RestTemplate restTemplate = new RestTemplate();
GsonHttpMessageConverter jsonConverter = new GsonHttpMessageConverter();
restTemplate.getMessageConverters().add(jsonConverter);
final String url = "http://restful.test.com/users";
User[] users = restTemplate.getForObject(url, User[].class);
Was it helpful?

Solution

Declare a custom deserializer for your class. Something like the one below.

Quote - The model

class Quote
{
    private String symbol;
    private String test; // the empty field we want to populate

    // getters() setters()
}

QuoteCreator deserializer - Populate test from symbol

class QuoteCreator implements JsonDeserializer<Quote>
{

    public Quote deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException
    {
        Gson g = new Gson();
        Quote a = g.fromJson(json, Quote.class);
        a.setTest(a.getSymbol());
        return a;
    }
}

Run

GsonBuilder b = new GsonBuilder();
b.registerTypeAdapter(Quote.class,new QuoteCreator());
Gson create = b.create();
Quote fromJson = (Quote) create.fromJson(file, Quote.class);

It works. You can use a more generic reflective solution to catch hold of a variety of classes, but its easier if the JSON is just corrected instead of resorting to a work around like this.

Generic deserializer

class MyCreator<T> implements JsonDeserializer<T>
{

    public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException
    {
        try
        {
            Gson g = new Gson();
            T a = g.fromJson(json, typeOfT);
            Class<? extends Object> class1 = a.getClass();
            Method getter = class1.getMethod("getSymbol", null);
            Method setter = class1.getMethod("setTest", String.class);
            String symbol = (String) getter.invoke(a, null);
            setter.invoke(a, symbol);
            return a;
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return null;
        }
    }
}

Usage

b.registerTypeAdapter(Quote.class,new MyCreator<Quote>());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top