使用 Gson 使用列表反序列化对象



我正在尝试反序列化一个 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'}

使用 Gson 的简单方法

Login dadosEmpresa = new Gson().fromJson(dados, Login.class);

但是,当我分析我的对象时,联系人列表和公司计划是空的。 反序列化后的对象

使用的类如下:

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 [..] }

我已经用过了

Type dados = new TypeToken<Login>() {}.getType();

但是由于我没有使用登录列表,因此我没有得到与第一种方法的任何区别效果。

注意:列表中未列出的所有其他数据均已正确设置。

如果您只是减少要反序列化的 JSON 文档的代码量和大小,那就太好了。

Gson 将其UnsafeAllocatorsun.misc.Unsafe.allocateInstance用于没有默认构造函数的类(至少对于我的 JVM 实例)。 这在未调用构造函数的情况下不需要分配对象,因为 Gson 无法正确构造内部类:您正在使用具有隐式编译器生成的构造函数的内部类来引用其外部类引用。 例如,具有以下类

class Login {
Empresa empresa;
class Empresa {
List<Contato> contato = new ArrayList<>();
class Contato {
int idContato;
String contato;
String tipoContato;
}
}
}

调用Login.Empresa.class.getDeclaredConstructors()将生成唯一的编译器生成的构造函数:q50361018.Login$Empresa(q50361018.Login)。 我真的不记得了,但初始值设定项似乎是在构造函数体之前调用的(并且可能是构造函数体的一部分)。 这意味着

final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
System.out.println(unsafeAllocator.newInstance(Login.Empresa.class).contato);

将返回始终设置为nullcontato因为没有调用构造函数,也没有调用字段初始值设定项。 但是,可以在反序列化期间设置contato字段。 至少如果您将其名称固定为listaContato或用@SerializedName('listaContato')注释字段。 因此,解决方案只是:

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;
}
}
}

或者更好的是,避免用于数据传输目的的内部类(如果可能的话,我个人不惜一切代价避免它们):

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;
}

上述所有三个类都假定它们是包级类。

演示:

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));
}

输出:

0 234234 Celular
0 323423 Celular
0 234234234 Celular

最新更新