Reputation: 13
I'm trying to deserialize a Json
{'empresa':{'areaAtuacao':{'areaAtuacao':'Primeiro','idAreaAtuacao':0},
'cnpjEmpresa':'561561','empresaAtivada':false,
'endereco':{'bairro':'Jardim Europa','cep':'85859318','cidade':'Foz do Iguaçu','complemento':'','estado':'PR','idEndereco':0,'logradouro':'Rua França','numero':'71'},
'idEmpresa':0,
'listaContato':[{'contato':'234234','idContato':0,'tipoContato':'Celular'},
{'contato':'323423','idContato':0,'tipoContato':'Celular'},
{'contato':'234234234','idContato':0,'tipoContato':'Celular'},
{'contato':'324','idContato':0,'tipoContato':'Celular'},
{'contato':'324','idContato':0,'tipoContato':'Celular'},
{'contato':'3','idContato':0,'tipoContato':'Celular'},
{'contato':'432','idContato':0,'tipoContato':'Celular'},
{'contato':'432','idContato':0,'tipoContato':'Celular'},
{'contato':'4','idContato':0,'tipoContato':'Celular'},
{'contato':'23','idContato':0,'tipoContato':'Celular'},
{'contato':'4234','idContato':0,'tipoContato':'Celular'},
{'contato':'34','idContato':0,'tipoContato':'Celular'}],
'listaHorario':
[{'diaSemana':{'diaSemana':'Segunda-Feira','idDiaSemana':0},'fimExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'fimIntervalo':{'year':2018 ,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'idHorarioEmpresa':0,'inicioExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'inicioIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58}},
{'diaSemana':{'diaSemana':'Terça-Feira','idDiaSemana':0},'fimExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'fimIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'idHorarioEmpresa':0,'inicioExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'inicioIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58}},
{'diaSemana':{'diaSemana':'Quarta-Feira','idDiaSemana':0},'fimExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'fimIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'idHorarioEmpresa':0,'inicioExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'inicioIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58}},
{'diaSemana':{'diaSemana':'Quinta-Feira','idDiaSemana':0},'fimExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'fimIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'idHorarioEmpresa':0,'inicioExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'inicioIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58}},
{'diaSemana':{'diaSemana':'Sexta-Feira','idDiaSemana':0},'fimExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'fimIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'idHorarioEmpresa':0,'inicioExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'inicioIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58}},{'diaSemana':
{'diaSemana':'Sábado','idDiaSemana':0},'fimExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'fimIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'idHorarioEmpresa':0,'inicioExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'inicioIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58}},
{'diaSemana':{'diaSemana':'Domingo','idDiaSemana':0},'fimExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'fimIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'idHorarioEmpresa':0,'inicioExpediente':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58},'inicioIntervalo':{'year':2018,'month':4,'dayOfMonth':15,'hourOfDay':20,'minute':16,'second':58}}],
'logoEmpresa':[-1,-40,-1,-32,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,-1,-31,33,65,69,120,105,102,0,0,73,73,42,0,8,0,0,0,9,0,15,1,2,0,18,0,0,0,-98,0,0,0,16,1,2,0,18,0,0,0,-80,0,0,0,18,1,4,0,1,0,0,0,1,0,0,0,26,1,5,0,1,0,0,0,122,0,0,0,27,1,5,0,1,0,0,0,-126,0,0,0,40,1,3,0,1,0,0,0,2,0,0,0,50,1,2,0,20,0,0,0,-118,0,0,0,19,2,3,0,1,0,0,0,1,0,0,0,105,-121,4,0,1,0,0,0,-62,0,0,0,36,1,0,0,72,0,0,0,1,0,0,0,72,0,0,0,1,0,0,0,50,48,49,56,58,48,53,58,49,53,32,50,48,58,49,54,58,49,57,0,69,109,117,108,97,116,111,114,45,71,111,108,100,102,105,115,104,0,69,109,117,108,97,116,111,114,45,71,111,108,100,102,105,115,104,0,7,0,0,-112,7,0,4,0,0,0,48,50,49,48,1,-111,7,0,4,0,0,0,1,2,3,0,10,-110,5,0,1,0,0,0,28,1,0,0,0,-96,7,0,4,0,0,0,48,49,48,48,1,-96,3,0,1,0,0,0,-1,-1,0,0,2,-96,4,0,1,0,0,0,-128,2,0,0,3,-96,4,0,1,0,0,0,-32,1,0,0,0,0,0,0,36,19,0,0,-24,3,0,0,2,0,1,2,4,0,1,0,0,0,66,1,0,0,2,2,4,0,1,0,0,0,-9,31,0,0,0,0,0,0,-1,-40,-1,-32,0,16,74,70,73,70,0,1,1,0,0,1,0,1,0,0,-1,-37,0,67,0,5,3,4,4,4,3,5,4,4,4,5,5,5,6,7,12,8,7,7,7,7,15,11,11,9,12,17,15,18,18,17,15,17,17,19,22,28,23,19,20,26,21,17,17,24,33,24,26,29,29,31,31,31,19,23,34,36,34,30,36,28,30,31,30,-1,-37,0,67,1,5,5,5,7,6,7,14,8,8,14,30,20,17,20],
'nomeFantasia':'jsdnjkfndkjn','publicoAlvo':'Unissex'},'encontrado':false,'idLogin':0,'senha':'B17EF6D19C7A5B1EE83B907C595526DCB1EB06DB8227D650D5DDA0A9F4CE8CD9','usuario':'51456'}
Using Gson's simple method
Login dadosEmpresa = new Gson().fromJson(dados, Login.class);
However, when I analyze my object, Contact List and Company Schedule are empty. Object after deserialization
The classes used are as follows:
public class Login {
private int idLogin;
private String usuario;
private String senha;
private String loginGoogle;
private Cliente cliente;
private Empresa empresa;
[...] Gets e Sets [..] }
public class Empresa {
private int idEmpresa;
private String nomeFantasia;
private String cnpjEmpresa;
private String descricaoEmpresa;
private byte[] logoEmpresa;
private boolean empresaAtivada;
private Calendar desativadaEm;
private String genero;
AreaAtuacao areaAtuacao = new AreaAtuacao();
Endereco endereco = new Endereco();
List<HorarioEmpresa> horarioEmpresa = new ArrayList<>();
List<Contato> contato = new ArrayList<>();
List<ServicoPrestado> servicoPrestado = new ArrayList<>();
[...] Gets e Sets [..] }
public class Contato {
private int idContato;
private String contato;
private String tipoContato;
[...] Gets e Sets [..] }
public class HorarioEmpresa {
private int idHorarioEmpresa;
private Calendar inicioExpediente;
private Calendar inicioIntervalo;
private Calendar fimIntervalo;
private Calendar fimExpediente;
private DiaSemana diaSemana;
[...] Gets e Sets [..] }
I already used it
Type dados = new TypeToken<Login>() {}.getType();
But since I'm not working with a Login list, I did not get any differentiated effect from the first method.
Note: All other data that is not in the List is being set correctly.
Upvotes: 1
Views: 91
Reputation: 21105
It would be nice if you'd simply reduce the amount of code and the size of the JSON document you are going to deserialize.
Gson uses its UnsafeAllocator
and sun.misc.Unsafe.allocateInstance
under the hood (at least for my JVM instance) for classes that do not have default constructors.
This is required no allocate objects without their constructors being invoked, because Gson cannot construct inner classes properly: you're using inner classes that have an implicit compiler-generated constructor to reference its outer class reference.
For example, having the following classes
class Login {
Empresa empresa;
class Empresa {
List<Contato> contato = new ArrayList<>();
class Contato {
int idContato;
String contato;
String tipoContato;
}
}
}
invoking Login.Empresa.class.getDeclaredConstructors()
will produce the only compiler-generated constructor: q50361018.Login$Empresa(q50361018.Login)
.
I don't really remember, but initializers seem to be invoked right before constructor bodies (and probably are a part of constructor bodies).
This means that
final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
System.out.println(unsafeAllocator.newInstance(Login.Empresa.class).contato);
will return contato
always set to null
because no constructor was invoked and no field initializers are invoked.
However, the contato
field can be set during deserialization.
At least if you fix its name to listaContato
or annotate the field with @SerializedName('listaContato')
.
So, the solution is just:
class Login {
Empresa empresa;
class Empresa {
// This is the solution
List<Contato> listaContato = new ArrayList<>();
// Or the following
// @SerializedName("listaContato")
// List<Contato> contato = new ArrayList<>();
// None of the solutions can fix the default empty array list though
class Contato {
int idContato;
String contato;
String tipoContato;
}
}
}
Or even better, avoid inner classes that serve data-transfer purposes (I personally avoid them at all costs if possible):
class Login {
Empresa empresa;
}
class Empresa {
// This will always be an empty array list even if there is `listaContato` in the JSON document
List<Contato> listaContato = new ArrayList<>();
}
class Contato {
int idContato;
String contato;
String tipoContato;
}
All three classes above assume that they are package-level classes.
Demo:
try ( final JsonReader jsonReader = Resources.getPackageResourceJsonReader(Q50361018.class, "whatever.json") ) {
final Login login = gson.fromJson(jsonReader, Login.class);
login.empresa.listaContato
.stream()
.limit(2)
.forEach(contato -> System.out.println(contato.idContato + " " + contato.contato + " " + contato.tipoContato));
}
Output:
0 234234 Celular
0 323423 Celular
0 234234234 Celular
Upvotes: 1