Converter Json para objeto

Delphi

05/02/2013

Sei que para converter objetos em Json utilizamos o TJSONMarshal e para fazer o inverso utilizamos o TJSONUnMarshal.
Tudo isso funciona até os objetos começarem a ficar mais complexos em sua estrutura...
Ao converter um objeto TACBrCTe para Json tudo bem, mas quando tento retornar o objeto utilizando o método TJSONUnMarshal retorna um "access violation".

Meu código:
Converte ACBrCTe para Json (Funciona)
function ACBrCTeToJSON(ACBrCTe: TACBrCTe): TJSONValue;
var
  m: TJSONMarshal;
begin
  if Assigned(ACBrCTe) then
  begin
    m := TJSONMarshal.Create(TJSONConverter.Create);

    try
      Result := m.Marshal(ACBrCTe);
      Exit;
    finally
      m.Free;
    end;
  end
  else
  begin
    Result := TJSONNull.Create;
    Exit;
  end;
end;


Converte Json para ACBrCTe (Erro)
function JSONToACBrCTe(json: TJSONValue): TACBrCTe;
var
   unm: TJSONUnMarshal;
begin
  if json is TJSONNull then
  begin
    Result := nil;
    Exit;
  end;

  unm := TJSONUnMarshal.Create;

  try
    Result := TACBrCTe(unm.Unmarshal(json));
    Exit;
  finally
    unm.Free;
  end;
end;
Gustavo Cruz

Gustavo Cruz

Curtidas 0

Respostas

Joel Rodrigues

Joel Rodrigues

05/02/2013

Em que linha ocorre o erro?
GOSTEI 0
Bruno Leandro

Bruno Leandro

05/02/2013

Ola Gustavo eu dei uma olhada e sem debugar talvez o erro seja ao atribuir um valor ao result, tente desta forma

function JSONToACBrCTe(json: TJSONValue): TACBrCTe;
var
unm: TJSONUnMarshal;
begin
Result := TACBrCTe.Create;
if json is TJSONNull then
begin
Result := nil;
Exit;
end;

unm := TJSONUnMarshal.Create;

try
Result := TACBrCTe(unm.Unmarshal(json));
Exit;
finally
unm.Free;
end;
end;
GOSTEI 0
Gustavo Cruz

Gustavo Cruz

05/02/2013

Então Joel o erro ocorre na função JSONToACBrCTe linha:
Result := TACBrCTe(unm.Unmarshal(json));


Bruno, mesmo colocando Result := TACBrCTe.Create; o erro continua.

O erro retornado é :
"Assertion failure (c:\arquivos de programas\embarcadero\rad studio\7.0\source\database\DBXJSONReflect.pas, line 1456)"
A pas informada no erro pertence ao JSON e a linha 1456 é a seguinte:

assert(JsonObj.Get(1).JsonString.Value=ID_NAME);


Estou usando o Delphi 2010 Update 3

Fiz um projeto com o exemplo do erro segue o código:

unit Principal;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,

  ACBrCTe,DBXJSON,DBXJSONReflect,pcnConversao, StdCtrls, Buttons;

type
  TfrmPrincipal = class(TForm)
    Label7: TLabel;
    edArqXml: TEdit;
    btnPasta: TBitBtn;
    OpenDialog1: TOpenDialog;
    ACBrCTe1: TACBrCTe;
    ACBrCTe2: TACBrCTe;
    procedure btnPastaClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    function ACBrCTeToJSON(ACBrCTe: TACBrCTe): TJSONValue;
    function JSONToACBrCTe(json: TJSONValue): TACBrCTe;
    procedure GetACBrCTe ( ACBrCTe:TJSONValue);
  public
    { Public declarations }
  end;

var
  frmPrincipal: TfrmPrincipal;

implementation

{$R *.dfm}

procedure TfrmPrincipal.btnPastaClick(Sender: TObject);
begin
  //Configuro para filtrar apenas arquivos xmls
  OpenDialog1.Title      := 'Selecione o CTe';
  OpenDialog1.DefaultExt := '*.xml';
  OpenDialog1.Filter     := 'Arquivos CTe (*.xml)|*.xml|Arquivos XML (*.xml)|*.xml|Todos os Arquivos (*.*)|*.*';

  if OpenDialog1.Execute then
  begin
    //limpo os conhecimentos
    ACBrCTe1.Conhecimentos.Clear;
    //pego o conhecimento (xml) selecionado
    ACBrCTe1.Conhecimentos.LoadFromFile(OpenDialog1.FileName);
    //Envio o CTe convertendo o objeto ACBrCTe em JSON, para a procedure validar o xml
    GetACBrCTe(ACBrCTeToJSON(ACBrCTe1));
  end;
end;

procedure TfrmPrincipal.FormCreate(Sender: TObject);
var
  Ok         : Boolean;
begin
  ACBrCTe1.Configuracoes.Certificados.NumeroSerie  := 'numero do certificado digital';

    //['1', '2', '3', '4', '5', '6', '7', '8', '9'],
    //[teNormal, teContingencia, teSCAN, teDPEC, teFSDA, teSVCAN, teSVCRS, teSVCSP, teOffLine]);

    ACBrCTe1.Configuracoes.Geral.FormaEmissao := StrToTpEmis( OK,IntToStr( 1 ) );
    ACBrCTe1.Configuracoes.Geral.Salvar       := True;
    ACBrCTe1.Configuracoes.WebServices.UF     := 'SP';

    //TpcnTipoAmbiente = (taProducao, taHomologacao);
    ACBrCTe1.Configuracoes.WebServices.Ambiente   := StrToTpAmb( Ok,IntToStr( 1 ) );
    ACBrCTe1.Configuracoes.WebServices.Visualizar := False;
end;

procedure TfrmPrincipal.GetACBrCTe(ACBrCTe: TJSONValue);
begin
  //Recebo o CTe no formato JSON e converto para ACBrCTe
  ACBrCTe2 := JSONToACBrCTe(ACBrCTe);
  //Valido o XML
  ACBrCTe2.Conhecimentos.Valida;
end;

//Converte JSON para ACBrCTe
function TfrmPrincipal.JSONToACBrCTe(json: TJSONValue): TACBrCTe;
var
   unm: TJSONUnMarshal;
begin
  Result := TACBrCTe.Create(nil);

  if json is TJSONNull then
  begin
    Result := nil;
    Exit;
  end;

  unm := TJSONUnMarshal.Create;

  try
    //Ao efetuar o cast retorna o erro :
    //Assertion failure (c:\arquivos de programas\embarcadero\rad studio\7.0\source\database\DBXJSONReflect.pas, line 1456)
    Result := TACBrCTe(unm.Unmarshal(json));
    Exit;
  finally
    unm.Free;
  end;
end;

//Converte ACBrCTe para JSON
function TfrmPrincipal.ACBrCTeToJSON(ACBrCTe: TACBrCTe): TJSONValue;
var
  m: TJSONMarshal;
begin
  if Assigned(ACBrCTe) then
  begin
    m := TJSONMarshal.Create(TJSONConverter.Create);

    try
      Result := m.Marshal(ACBrCTe);
      Exit;
    finally
      m.Free;
    end;
  end
  else
  begin
    Result := TJSONNull.Create;
    Exit;
  end;
end;

end.



Obrigado pela atenção de todos.
GOSTEI 0
POSTAR