Incremental parsing is a term COINED by myself. It is mainly used in such scenarios. When a mobile terminal requests JSON data from the server, in consideration of the precious traffic resources, if the local server has already requested complete information, it is generally used to deliver an updated field of model, instead of delivering the complete model every time. For example, if we ask the server for user information, the complete data format might be:

{“age”:20,”id”:1,”name”:” zhang SAN “,”sex”:” male “}

The ID, name, and sex of User may remain unchanged, while age may change. When the client refreshes the User information, the server only needs to send the age information to save traffic. The data format may be:

{“age”:25,”id”:1}

Only age changes, so only age information is delivered, and id is used as the identification field. When parsing with Gson, we usually call the fromJson function directly, which takes two arguments, a JSON string and a parsed Model class. Redefining a SubUser class to handle the parsing and assign the value to User is extremely inflexible. The updated fields must be written to death by the client. If the name or sex changes next time, Does the SubUser class need to be modified and published?

How about a function like fromJson where the second argument is no longer a class, but an instance, and new JSON data updates only certain fields of that instance? Gson will call the default constructor new to create an instance of the model. Can we not make it new and directly parse the original instance? You can register Gson with an InstanceCreator, which is an interface that, as the name suggests, provides the user with a function to initialize the model:

public interface InstanceCreator<T> {
  
  public T createInstance(Type type);
}
Copy the code

This allows us to resolve incremental updates with the original user as the initialized instance. So this is parsing object, so you can do this. If it is a list, how to perform incremental parsing? The original list can not be used as the return value, so I do not have a good idea, just split the list into objects for parsing.

Write a simple demo below:

The User class:

public class User{

    public long id;

    public String name;

    public String sex;

    public int age;

    public long getId() {
        returnid; }}Copy the code

GsonCreatorHelper class:

public class GsonCreatorHelper {

    public static User fromJson(String json, final User old) {
        try {
            JSONObject object = new JSONObject(json);
            long id = object.getLong("id");
            if (id == old.getId()) {
                Gson gson = new GsonBuilder().registerTypeAdapter(User.class, new InstanceCreator<User>() {
                    @Override
                    public User createInstance(Type type) {
                        return old;
                    }
                }).create();
                return gson.fromJson(json, User.class);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return new Gson().fromJson(json, User.class);
    }

    public static List<User> fromJson(String json, final List<User> old) {
        try {
            List<User> result = new ArrayList<>();
            JSONArray array = new JSONArray(json);
            for (int i = 0; i < array.length(); i++) {
                JSONObject object = array.getJSONObject(i);
                final long id = object.getLong("id");
                Gson gson = new GsonBuilder().registerTypeAdapter(User.class, new InstanceCreator<User>() {
                    @Override
                    public User createInstance(Type type) {
                        return getUserById(old, id);
                    }
                }).create();
                result.add(gson.fromJson(object.toString(), User.class));
            }
            return result;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return new Gson().fromJson(json, new TypeToken<List<User>>() {
        }.getType());
    }

    private static User getUserById(List<User> users, long id) {
        for (User user : users) {
            if (user.getId() == id) {
                returnuser; }}returnnew User(); }}Copy the code

MainActivity test class:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String json1 = "{\" age \ ": 20, \ \" id ": 1, \" name \ ": \" zhang SAN \ ", \ "sex \" : \ "m \"}";
        String json2 = "{\"age\":23,\"id\":1}";
        String json3 = "[{\" age \ ": 20, \ \" id ": 1, \" name \ ": \" zhang SAN \ ", \ "sex \" : \ "m \"}, {\ "age \" : 23, \ \ "id" : 2, \ "name \" : \ \ "", dick, and harry, \" sex \ ": \" m \} "]";
        String json4 = "[{\"age\":23,\"id\":1},{\"age\":33,\"id\":2}]";

        User user1 = new Gson().fromJson(json1, User.class);
        Log.e("user1", new Gson().toJson(user1));

        User user2 = GsonCreatorHelper.fromJson(json2, user1);
        Log.e("user2", new Gson().toJson(user2));

        List<User> user3 = new Gson().fromJson(json3, new TypeToken<ArrayList<User>>() {}.getType());
        Log.e("user3", new Gson().toJson(user3));

        List<User> user4 = GsonCreatorHelper.fromJson(json4, user3);
        Log.e("user4", new Gson().toJson(user4));
    }
Copy the code
10-08 18:18:41. 419, 28438-28438 / com. Please gsoninstancecreatortest E/user1: {"age": 20."id": 1,"name":"Zhang"."sex":"Male"10-08 18:18:41}. 425, 28438-28438 / com. Please gsoninstancecreatortest E/user2: {"age": 23."id": 1,"name":"Zhang"."sex":"Male"10-08 18:18:41}. 436, 28438-28438 / com. Please gsoninstancecreatortest E/user3: [{"age": 20."id": 1,"name":"Zhang"."sex":"Male"}, {"age": 23."id": 2."name":"Bill"."sex":"Male"10-08 18:18:41}]. 441, 28438-28438 / com. Please gsoninstancecreatortest E/user4: [{"age": 23."id": 1,"name":"Zhang"."sex":"Male"}, {"age": 33,"id": 2."name":"Bill"."sex":"Male"}]
Copy the code

From the results, we can see that user2 and user4 both parse the new JSON data based on user1 and user3. And you’re done!