Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 08-10-2015
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 30
jhonny Va camino a la famajhonny Va camino a la fama
TJsonArray con corchetes de más

Buenos días, tardes, noches... a todos segun corresponda.

Hoy vengo a plantear un caso y saber si a ustedes les ha pasado esto y si lo han solucionado de alguna manera diferente.

Tengo Un DataSnap Server al cual me conecto por medio de su TDSHTTPService utilizando sus cualidades REST por medio de JSon.

En algun momento he necesitado compartir imagenes, archivos o en fin cualquier TStream, así que tengo una función en el server, parecida a esta, que devuelve el TStream serializado como TJsonArray, así:

Código Delphi [-]
function TServerMethods.GetImagen: TJSONArray;
var
  vStream: TStream;
begin
  vStream := TStream.Create;
  try
    vStream := GetImagenInterno;

    Result := TDBXJSONTools.StreamToJSON(vStream, 0, vStream.Size);
  finally
    vStream.Free;
  end;
end;

Básicamente lo que hace es cargar un archivo y devolverlo serializado en un TJsonArray de enteros, que debería verse así, por ejemplo:
Código:
[1, 5, 7, 8, 9...]
Pero por alguna razón el server envía dicho TJsonArray, así:
Código:
[[1, 5, 7, 8, 9...]]
Como pueden ver, por alguna razón por mí desconocida hasta el momento, agrega un corchete de más al inicio y un corchete de más, al final... por lo que al tratar de hacer lo siguiente en el cliente no convierte correctamente el arreglo a TStream:

Código Delphi [-]
var
  vJArray: TJSONArray;
  vMemStream: TMemoryStream;
begin
  vMemStream := TMemoryStream.Create;
  try
    RESTRequest2.Execute;

    vJArray := TJSONObject.ParseJSONValue(RESTResponse2.Content) as TJSONArray;

    vMemStream.LoadFromStream(TDBXJSONTools.JSONToStream(vJArray)); //Con esto convierto de TJSonArray a TStream 

    ImageViewer1.Bitmap.LoadFromStream(vMemStream);

  finally
    vMemStream.Free;
  end;
end;

Por lo que si hago una "chapuza" (Como la siguiente) para quitar de la cadena de texto recibida ese corchete incial y final de más... pues me muestra la imagen y todo aparenta estar bien, pero no es algo optimo ya que es un paso de más que finalmente afectará el rendimiento de la aplicación cliente:

Código Delphi [-]
var
  vJArray: TJSONArray;
  vMemStream: TMemoryStream;
  vCadena: String;
begin
  vMemStream := TMemoryStream.Create;
  try
    RESTRequest2.Execute;

    vCadena := DMPrincipal.RESTResponse2.Content;
    vCadena[1] := ' ';
    vCadena[Length(vCadena)] := ' ';


    vJArray := TJSONObject.ParseJSONValue(vCadena) as TJSONArray;

    vMemStream.LoadFromStream(TDBXJSONTools.JSONToStream(vJArray)); //Con esto convierto de TJSonArray a TStream 

    ImageViewer1.Bitmap.LoadFromStream(vMemStream);

  finally
    vMemStream.Free;
  end;
end;

La duda finalmente es, ¿Qué debería hacer para que el server me devuelva de manera natural y sin este tipo de "chapuzeras" correctamente el TJsonArray, sin esos corchetes de más?

Por su tiempo y atención, muchas gracias
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/
Responder Con Cita
  #2  
Antiguo 08-10-2015
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Ni idea. Pero más que pensar que te está insertando corchetes extra piensa que te está devolviendo un arreglo cuya única entrada es el arreglo que esperas. Quizá así tengas más idea de porqué lo hace y en lugar de quitar los corchetes extra simplemente toma el primer elemento del arreglo devuelto que, como dije, será el arreglo que esperabas.

// Saludos
Responder Con Cita
  #3  
Antiguo 08-10-2015
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 30
jhonny Va camino a la famajhonny Va camino a la fama
Cita:
Empezado por roman Ver Mensaje
Ni idea. Pero más que pensar que te está insertando corchetes extra piensa que te está devolviendo un arreglo cuya única entrada es el arreglo que esperas. Quizá así tengas más idea de porqué lo hace y en lugar de quitar los corchetes extra simplemente toma el primer elemento del arreglo devuelto que, como dije, será el arreglo que esperabas.

// Saludos
Roman, definitivamente sos grande . Gracias por la luz he podido verlo de manera diferente... de momento el cliente ha quedado así:

Código Delphi [-]
var
  vJArray: TJSONArray;
  vMemStream: TMemoryStream;
begin
  vMemStream := TMemoryStream.Create;
  try
    RESTRequest2.Execute;

    vJArray := TJSONObject.ParseJSONValue(vCadena) as TJSONArray;

    vMemStream.LoadFromStream(vMemStream.LoadFromStream
      (TDBXJSONTools.JSONToStream(TJSONArray(vJArray.Items[0]))); //Con esto convierto de TJSonArray a TStream el arreglo que se encontraba en la posición 0

    ImageViewer1.Bitmap.LoadFromStream(vMemStream);

  finally
    vMemStream.Free;
  end;
end;

Ahora, a ver en el server el asunto, gracias de nuevo.
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/
Responder Con Cita
  #4  
Antiguo 08-10-2015
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
¡Qué bueno que te haya servido! Para mi, esto que pones es contra natura Todo el delphi actual lo es

De entrada, veo DBX. ¿Eso se refiere a DBExpress? Y, si es así, ¿por qué DBExpress implementa métodos para convertir streams a formato JSon?

// Saludos
Responder Con Cita
  #5  
Antiguo 08-10-2015
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 30
jhonny Va camino a la famajhonny Va camino a la fama
Cita:
Empezado por roman Ver Mensaje
¡Qué bueno que te haya servido! Para mi, esto que pones es contra natura Todo el delphi actual lo es
Bueno, es que analizando el asunto gracias a lo que me has comentado, me doy cuenta que todo valor de tipo JSon, el server DataSnap, lo devuleve como si de un TJsonValue se tratara, encerrandolo por ende dentro de esos corchetes, entonces de ahora en adelante, no debo pretender recibir un Json puro, sino un Json puro dentro de un TJsonValue.

Cita:
Empezado por roman Ver Mensaje
De entrada, veo DBX. ¿Eso se refiere a DBExpress? Y, si es así, ¿por qué DBExpress implementa métodos para convertir streams a formato JSon?
Bueno, es que en principio el DataSnap está basado en bibliotecas DBExpress, pero a medida del tiempo han ido vinculando todas estas funcionalidades de REST, por lo que han ido vinculando nuevas unidades expecificas para tal uso, pero en algunos casos como en este siguen en aquellas unidades, supongo que por simple referencia. Aunque es sólo mi apreciación, es muy probable que esté equivocado.
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/
Responder Con Cita
  #6  
Antiguo 08-10-2015
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por jhonny Ver Mensaje
Bueno, es que en principio el DataSnap está basado en bibliotecas DBExpress, pero a medida del tiempo han ido vinculando todas estas funcionalidades de REST, por lo que han ido vinculando nuevas unidades expecificas para tal uso, pero en algunos casos como en este siguen en aquellas unidades, supongo que por simple referencia. Aunque es sólo mi apreciación, es muy probable que esté equivocado.
Claro, DBExpress evolucionó a DataSnap. Pero a lo que voy es a esto:

Tanto JSon, como streams son cosas independientes de DataSnap. Entonces, ¿qué pitos toca DataSnap implementando estas conversiones? No es su tarea.

Es decir, las bibliotecas de Delphi se han convertido en mounstruos hacelo-todo

// Saludos
Responder Con Cita
  #7  
Antiguo 08-10-2015
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Cita:
Empezado por jhonny Ver Mensaje
devolverlo serializado en un TJsonArray de enteros, que debería verse así, por ejemplo:
Código:
[1, 5, 7, 8, 9...]
Oe, y no es mas logico devolver binarios usando base64??
__________________
El malabarista.
Responder Con Cita
  #8  
Antiguo 09-10-2015
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 30
jhonny Va camino a la famajhonny Va camino a la fama
Cita:
Empezado por roman Ver Mensaje
Claro, DBExpress evolucionó a DataSnap. Pero a lo que voy es a esto:

Tanto JSon, como streams son cosas independientes de DataSnap. Entonces, ¿qué pitos toca DataSnap implementando estas conversiones? No es su tarea.

Es decir, las bibliotecas de Delphi se han convertido en mounstruos hacelo-todo

// Saludos
Bueno, los DBX implementan esas funciones para poder hacer conversiones entre JSon y sus respectivos valores, por ejemplo convertir un Arreglo Json a un DBXReader para luego poder leerlo como si se tratara de un DataSet (Nunca lo he hecho manualmente, pero supongo que así es). Entonces uno aprovecha que DBX tiene esas funciones para implementarlas en las demás cosas que necesita.

Cita:
Empezado por mamcx
Oe, y no es mas logico devolver binarios usando base64??
Lo que es logico para unos, no es logico para los demás... en ese orden de ideas... ¿para ti, por qué es más logico?... ¿Compatibilidad, velocidad de transmisión, estandar, ninguna de las anteriores y/o todas las anteriores?, Delphi tiene sus funciones Encode y Decode en base 64, pero ya que no sé, ¿cual sería la razón logica para cambiar a binario base64?
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/
Responder Con Cita
  #9  
Antiguo 09-10-2015
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
La razon es que ese es el medio mas usado para transmitir informacion binaria por http, y es un estándar en eso desde hace rato:

https://es.wikipedia.org/wiki/Base64

Ademas, estoy casi seguro (porque no se como seran tus datos ) que debe ser mas pesado pasar por cada integer que en base64 (u otro encoding especializado en binarios), y es mas "natural", osea, un valor=un binario.

Ahora si asi te da ok. Puede que con compresion salga bien...
__________________
El malabarista.
Responder Con Cita
  #10  
Antiguo 11-10-2015
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 30
jhonny Va camino a la famajhonny Va camino a la fama
Cita:
Empezado por mamcx Ver Mensaje
La razon es que ese es el medio mas usado para transmitir informacion binaria por http, y es un estándar en eso desde hace rato:

https://es.wikipedia.org/wiki/Base64

Ademas, estoy casi seguro (porque no se como seran tus datos ) que debe ser mas pesado pasar por cada integer que en base64 (u otro encoding especializado en binarios), y es mas "natural", osea, un valor=un binario.

Ahora si asi te da ok. Puede que con compresion salga bien...
Hola, buenas noches, acabo de hacer el cambio para comparar el asunto, no sólo desde el tema de compatibilidad, sino también para ver cual de los 2 metodos me sirve más en cuanto a rendimiento y transmisión de dichos datos... bueno, como bien indicabas me he decidido por utilizar Base64, pues no consume tanto performance del server despues de todo, es más comprimido y además es más utilizado... acá pongo el código del server en Base64, por si a alguien más le sirve.

De hecho Embarcadero recomienda usar el método anterior (TDBXJSONTools.JSONToStream) únicamente en llamadas asincronas y si el flujo de información no es muy alto.

Código Delphi [-]
function TServerMethods.GetFileBase64: String;
var
  vStream: TStream;
  vStringStream: TStringStream;
  vBase64: TBase64Encoding;
begin
  vStream := TStream.Create;
  vStringStream := TStringStream.Create;
  try
    vStream := GetFileInterno; //Eso devuelve un TStream luego de comprimir el archivo en cuestión y hacer ciertas validaciones...

    vBase64 := TBase64Encoding.Create;
    vBase64.Encode(vStream, vStringStream);

    Result := vStringStream.DataString;
  finally
    vStream.Free;
    vStringStream.Free;
    vBase64.Free;
  end;
end;
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/

Última edición por jhonny fecha: 11-10-2015 a las 07:29:18.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Los corchetes de Eduarcol JoseFco La Taberna 44 15-08-2008 12:19:55


La franja horaria es GMT +2. Ahora son las 13:40:10.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi