Serialization/Deserialization of Realm Objects Using Gson with Custom Json Adapter
Any experienced developer knows that sometimes the standard solutions are not sufficiently productive or simple enough for the project. Then you have to apply ingenuity and write a unique custom solution.
While working on one of our projects, we ran into the fact that the use of such typical solutions increased development time by more than a week and significantly complicated the project. As a result of brainstorming, in a day we wrote a custom adapter, saved time and have combined two industry standards into a harmoniously interconnected model.
Today it is difficult to imagine an application that does not use a database, whether it runs on a server, personal computer or mobile device. From simple games to serious business applications, they all process, read and write datasets.
Database Management Systems (DBMS) are based on the database models - special structures designed to work with the data. All databases are very different in how they store and process their data.
At the heart of the classic databases lies a relational data model. The principles of the relational model were laid in the period of 1969-1970 by an American scholar E. F. Codd, who worked in the IBM corporation at the time. Being a mathematician by education, he has brought the rigorous mathematical principles and accuracy into the database management, which earlier systems lacked. Although the relational approach was not established immediately, it should be noted that by the end of the 1970s, almost all DBMS products were based on a relational approach. The vast majority of research in the database field for the past 35 years was also conducted in this direction.
The relational model only involves handling of atomic data and denies any processing of unstructured information. As a result, the storage of images, audio or video data becomes impossible.
In this regard, in recent years NoSQL-databases technology is actively developing, such databases are implemented in modern DBMSs like Hadoop, MongoDB, DynamoDB, Azure Data Storage etc. NoSQL removes most of the restrictions of the relational model (lack of performance, time-consuming scaling, insufficient capacity in the cluster) and facilitates the storage means and the data access. Such databases use an unstructured approach (creation of a structure on the fly), thereby removing the restrictions of rigid connections and offering different types of access to specific data.
The above-mentioned project uses the similar DBMS – Realm. It has recently appeared on the market but has already earned considerable popularity because of its notable advantages and opportunities. Realm exists in native implementation for mobile platforms (Objective-C, Swift, React), cross-platform (Xamarin) and desktop (Java).
Read also: The Pros and Cons of AngularJS vs ReactJS
To get data from the server, the library, which has become the industry standard - Retrofit 2.0 is used. The received data must be stored in the database. In the absence of a direct interface to the database, in a normal situation, it would be processed by an individual employee – they would insert entries into the database manually. However, it takes a lot of time and effort, so we wrote a solution that automatically handles the server responses and inserts them into the database. For translation, the built-in library, developed by Google is used - gson. This library is designed to convert the Java objects to the JSON text format (serialization) and back (deserialization).
Regardless of the query type, the server data is seamlessly introduced into the device’s local database. The solution is universal for all types of servers and queries.
The course of the process:
1. With the use of Retrofit, receive the data from the server in the form of a text string in JSON format.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
final Call<ResponseContainer<List<Recipient>>> recipientsCall = api.getRecipients(null, null, null); executor.execute(new Runnable() { @Override public void run() { try { Response<ResponseContainer<List<Recipient>>> response = recipientsCall.execute(); final ResponseContainer<List<Recipient>> container = validateResponse(response, callback); if (container == null) { return; } handler.post(new Runnable() { @Override public void run() { List<Recipient> data = container.getData(); dbBridge.setRecipients(data); callback.onSuccess(); } }); } catch (IOException e) { e.printStackTrace(); } } }) |
2. Using gson, the resulting string is parsed and the data is reflected into the data models used by Realm.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
while (in.hasNext()) { String name = in.nextName(); Field field = getField(name); if (field == null) { in.skipValue(); continue; } Method setter = getSetter(field); if (setter == null) { in.skipValue(); continue; } try { setter.invoke(object, gson.fromJson(in, field.getType())); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } |
3. Ready data models are stored in the database.
1 2 3 |
realm.beginTransaction(); realm.copyToRealmOrUpdate(recipient); realm.commitTransaction(); |
A complete listing of the finished working adapter can be found on our GitHub.