I recently started working with GSON and somewhat complex data models, with related classes.
The truth is that at the beginning I did not have very clear how to do things, what helped me was to safeguard the whole data model as I had designed it in each table and build my JSON according to that model, respecting the reality of the data .
I would like to present a somewhat long and complex model, but one that can help to deal with the problem in a complete way, since it includes, at many points, nested data at more than one level.
The JSON that occurs is as follows:
{
"breviario": {
"metaLiturgia": {
"fecha" : "Domingo 25 de noviembre del 2018",
"tiempo" : "TIEMPO ORDINARIO",
"semana" : "Semana XXXIV",
"mensaje": "",
"salterio": "<small></small>",
"color": 0,
"meta":0,
"idTiempo": "08"
},
"santo": {
"nombre": "",
"vida": ""
},
"visperas": {
"himno" : {
"texto": "Oh príncipe absoluto de los siglos,~oh Jesucristo, rey de las naciones:~te confesamos árbitro supremo~de las mentes y de los corazones.§En la tierra te adoran los mortales~y los santos te alaban en el cielo,~unidos a sus voces te aclamamos~proclamándote rey del universo.§Oh Jesucristo, príncipe pacífico:~somete a los espíritus rebeldes,~y haz que encuentren el rumbo los perdidos~y que en un solo aprisco se congreguen.§Para eso pendes de una cruz sangrienta,~y abres en ella tus divinos brazos;~para eso muestras en tu pecho herido~tu ardiente corazón atravesado.§Para eso estás oculto en los altares~tras las imágenes del pan y el vino;~para eso viertes de tu pecho abierto~sangre de salvación para tus hijos.§Por regir con amor el universo,~glorificado seas, Jesucristo,~y que contigo y con tu eterno Padre~también reciba gloria el Santo Espíritu. Amén."
},
"salmodia": {
"tipo":0,
"salmoCompleto": [
{
"orden": "1",
"antifona": "Se sentará sobre el trono de David para reinar eternamente. Aleluya.",
"ref": "Salmo 109, 1-5. 7",
"tema": "El Mesías, Rey y Sacerdote",
"intro": "Él debe reinar hasta poner~todos sus enemigos bajo sus pies.~(1Co 15, 25)",
"parte": "",
"salmo": "Oráculo del Señor a mi Señor:_«Siéntate a mi derecha,_y haré de tus enemigos estrado de tus pies.»§Desde Sión extenderá el Señor_el poder de tu cetro:_somete en la batalla a tus enemigos.§«Eres príncipe desde el día de tu nacimiento,_entre esplendores sagrados;_yo mismo te engendré, como rocío,_antes de la aurora.»§El Señor lo ha jurado y no se arrepiente:_«Tú eres sacerdote eterno,_según el rito de Melquisedec.»§El Señor a tu derecha, el día de su ira,_quebrantará a los reyes.§En su camino beberá del torrente,_por eso levantará la cabeza."
},
{
"orden": "2",
"antifona": "Tu reinado es un reinado perpetuo, tu gobierno va de edad en edad.",
"ref": "Salmo 144, 1-13b",
"tema": "",
"intro": "",
"parte": "",
"salmo": "Te ensalzaré, Dios mío, mi rey;_bendeciré tu nombre por siempre jamás._Día tras día te bendeciré_y alabaré tu nombre por siempre jamás.§Grande es el Señor, merece toda alabanza,_es incalculable su grandeza;_una generación pondera tus obras a la otra,_y le cuenta tus hazañas.§Alaban ellos la gloria de tu majestad,_y yo repito tus maravillas;_encarecen ellos tus temibles proezas,_y yo narro tus grandes acciones;_difunden la memoria de tu inmensa bondad,_y aclaman tus victorias.§El Señor es clemente y misericordioso,_lento a la cólera y rico en piedad;_el Señor es bueno con todos,_es cariñoso con todas sus creaturas.§Que todas tus creaturas te den gracias, Señor,_que te bendigan tus fieles;_que proclamen la gloria de tu reinado,_que hablen de tus hazañas;§explicando tus proezas a los hombres,_la gloria y majestad de tu reinado._Tu reinado es un reinado perpetuo,_tu gobierno va de edad en edad."
},
{
"orden": "3",
"antifona": "Lleva escrito sobre su manto y en su estandarte este nombre: «Rey de reyes y Señor de señores.» A él la gloria y el poder por los siglos de los siglos.",
"ref": "Cántico¦Cf. Ap 19, 1-2. 5-7",
"tema": "Las bodas del Cordero",
"intro": "",
"parte": "",
"salmo": "Aleluya._La salvación y la gloria y el poder son de nuestro Dios._⟨ⱤAleluya.⟩_Porque sus juicios son verdaderos y justos._ⱤAleluya, ⟨aleluya⟩.§Aleluya._Alabad al Señor, sus siervos todos._⟨ⱤAleluya.⟩_Los que le teméis, pequeños y grandes._ⱤAleluya, ⟨aleluya⟩.§Aleluya._Porque reina el Señor, nuestro Dios, dueño de todo._⟨ⱤAleluya.⟩_Alegrémonos y gocemos y démosle gracias._ⱤAleluya, ⟨aleluya⟩.§Aleluya._Llegó la boda del Cordero._⟨ⱤAleluya.⟩_Su esposa se ha embellecido._ⱤAleluya, ⟨aleluya⟩."
}
]},
"lecturaBreve": {
"ref": "1Co 15, 25-28",
"texto": "Cristo debe reinar hasta poner todos sus enemigos bajo sus pies. El último enemigo aniquilado será la muerte. Porque Dios ha sometido todas las cosas bajo sus pies. Mas cuando él dice que «todo está sometido», es evidente que se excluye a aquel que ha sometido a él todas las cosas. Cuando hayan sido sometidas a él todas las cosas, entonces también el Hijo se someterá a aquel que ha sometido a él todas las cosas, para que Dios sea todo en todo.",
"responsorio": "Tu trono, Señor, permanece para siempre.|Tu cetro real es cetro de rectitud.|Permanece para siempre.|Gloria al Padre, y al Hijo, y al Espíritu Santo.",
"forma": 6001230
},
"magnificat": {
"antifona": "«Me ha sido dado todo poder en el cielo y en la tierra», dice el Señor.",
"texto":""
},
"preces": {
"intro": "Hermanos, adoremos a Cristo Rey, el cual existe antes que todas las cosas, y en quien todas las cosas tienen su razón de ser. Elevemos a él nuestra voz, clamando:|Que venga tu reino, Señor.|Con la confianza que nos da el ser participantes de la realeza de Cristo y coherederos de su reino, elevemos nuestra voz al Padre celestial:",
"texto": "Cristo, nuestro rey y pastor, congrega a tus ovejas de todos los puntos de la tierra≠y apaciéntalas en verdes praderas de pastos abundantes.§Cristo, nuestro salvador y nuestro guía, reúne a todos los hombres dentro de tu pueblo santo: sana a los enfermos, busca a los extraviados, conserva a los fuertes,≠haz volver a los que se han alejado, congrega a los dispersos, alienta a los desanimados.§Juez eterno, cuando pongas tu reino en manos de tu Padre, colócanos a tu derecha≠y haz que poseamos el reino que nos ha sido preparado desde la creación del mundo.§Príncipe de la paz, quebranta las armas homicidas≠e infunde en todas las naciones el amor a la paz.§Heredero universal de todas las naciones, haz entrar a la humanidad con todos sus bienes al reino de tu Iglesia que tu Padre te ha dado,≠para que todos, unidos en el Espíritu Santo, te reconozcan como su cabeza.∞Cristo, primogénito de entre los muertos y primicia de los que duermen,≠admite a los fieles difuntos a la gloria de tu resurrección."
},
"oracion": "Dios todopoderoso y eterno,~que quisiste restaurar todas las cosas~por tu amado Hijo, Rey del universo,~te pedimos que la creación entera,~liberada de la esclavitud del pecado,~te sirva y te alabe eternamente.~Por nuestro Señor Jesucristo, tu Hijo,~que vive y reina contigo~en la unidad del Espíritu Santo,~y es Dios, por los siglos de los siglos."
}
}
}
To make it short, let's take some examples of this JSON.
This part of the JSON represents the table santo
of the database, which has two columns: nombre, vida
:
"santo": {
"nombre": "",
"vida": ""
}
The class is like this:
public class Santo {
private String nombre;
private String vida;
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getVida() {
return vida;
}
public void setVida(String vida) {
this.vida = vida;
}
}
Then, you can see a much more complex visperas
node with several primitive elements (string, int, etc) and other elements that are of another class . If you look at the node, you can deduce that himno, salmodia, lecturaBreve, magnificat y preces
are independent classes that are part of visperas
, while oracion
is a primitive element (string) that is also part of vespers.
The class visperas
is therefore presented as follows:
public class Visperas {
private Himno himno;
private Salmodia salmodia;
private LecturaBreve lecturaBreve;
private Magnificat magnificat;
private Preces preces;
private String oracion;
public Himno getHimno() {
return himno;
}
public void setHimno(Himno himno) {
this.himno = himno;
}
public Salmodia getSalmodia() {
return salmodia;
}
public void setSalmodia(Salmodia salmodia) {
this.salmodia = salmodia;
}
public LecturaBreve getLecturaBreve() {
return lecturaBreve;
}
public void setLecturaBreve(LecturaBreve lecturaBreve) {
this.lecturaBreve = lecturaBreve;
}
public Magnificat getMagnificat() {
return magnificat;
}
public void setMagnificat(Magnificat magnificat) {
this.magnificat = magnificat;
}
public Preces getPreces() {
return preces;
}
public void setPreces(Preces preces) {
this.preces = preces;
}
public String getOracion() {
return oracion;
}
public void setOracion(String oracion) {
this.oracion = oracion;
}
}
If you want to continue analyzing, you can see that within the node salmodia
there is still another node that is a class of its own, it is called: salmoCompleto
.
The class Salmodia
appears like this:
public class Salmodia {
public int tipo;
public List<SalmoCompleto> salmoCompleto;
/*Un getter super interesante*/
public SpannableStringBuilder getSalmoCompleto() {
for (SalmoCompleto s : salmoCompleto) {
/*
*Aquí doy formato a cada elemento del salmo:
*tema, texto, parte, etc
*y lo devuelvo formateado
*/
}
}
You can see that salmocompleto
is defined in Salmodia
as a list of type SalmoCompleto
: List<SalmoCompleto>
The class SalmoCompleto
is defined as follows:
public class SalmoCompleto {
private String orden;
private String antifona;
private String ref;
private String tema;
private String intro;
private String parte;
private String salmo;
//getter setter
}
This is very interesting and very useful. Because for example I need each psalm, be 3, be 50, bring a specific format. To say something, that the letter color of member tema
is in red. Well, all that complete work I do in the method getSalmoCompleto
of the class Salmodia
, which is going through the array of psalms and formatting.
Get references
I show an example how I get each reference of the different nodes of my JSON:
Gson gson = new Gson();
JSONObject jsonBreviario = jsonDatos.getJSONObject("breviario");
Breviario breviario = gson.fromJson(String.valueOf(jsonBreviario), Breviario.class);
MetaLiturgia meta = breviario.getMetaLiturgia();
Santo santo = breviario.getSanto();
Visperas visperas = breviario.getVisperas();
Himno himno = visperas.getHimno();
Salmodia salmodia = visperas.getSalmodia();
LecturaBreve lecturaBreve = visperas.getLecturaBreve();
Magnificat magnificat = visperas.getMagnificat();
Preces preces = visperas.getPreces();
For example, a process that could be complicated, such as obtaining the complete psalm with different formats, colors, and font sizes, becomes as simple as doing this:
sb.append(salmodia.getSalmoCompleto());
the method does the rest.
Have a clear criterion
At first I was a bit lost with GSON. My criteria was: build a JSON that respects my data model. That is, if I have a table himno
, the JSON must have a node called himno
, if I have a table visperas
, which in turn uses elements from other tables, my JSON must have a node visperas
and the sub-nodes that are needed.
From there we can deduce that the most important thing is to structure your JSON well, respecting your data model . It would have been apparently easier not to create a node salmodia
with a sub-node salmoCompleto
and put the psalm array directly into the main node. But it turns out that there are other tables that also use salmodia
, tables similar to visperas
, but with another function. If I by (apparent) ease I get to salmoCompleto
of the node salmodia
and I put it directly in the node visperas
, I do nothing but disrespect the data design (a full psalm is a full psalm), and also complicate me life when you have to format each element of the psalm or when you have to use it from another of the classes that also use elements of type SalmoCompleto
.
A very useful tool
There is a tool that helped me a lot to correctly implement the data model. Once you have the JSON built according to your data model, you can paste it and it will generate the class in a correct way. This is jsonutils
, an online tool that generates classes from a JSON. The only criticism I can make is that you create the members of the class as public
, I in my case change them to private
to make the management of the members go through the getter and the setter .
PS:
I hope this answer will be helpful for your data model. If there is any doubt you can ask in comments.