Десериализовать объект с помощью списка с помощью Gson - PullRequest
0 голосов
/ 16 мая 2018

Я пытаюсь десериализовать 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();

Но так как я не работаюсо списком входа в систему я не получил никакого дифференцированного эффекта от первого метода.

Примечание. Все остальные данные, которых нет в списке, установлены правильно.

1 Ответ

0 голосов
/ 16 мая 2018

Было бы неплохо, если бы вы просто сократили объем кода и размер документа JSON, который вы собираетесь десериализовать.

Gson использует свои UnsafeAllocator и sun.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);

вернет contato, всегда установленное на null, потому что не был вызван конструктор и не инициализированы поля. Однако поле 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...