Saltar al contenido

Delphi analizar JSON array o array

El paso a paso o código que encontrarás en este artículo es la resolución más rápida y válida que hallamos a tu duda o problema.

Solución:

Para nuevos lectores que buscan estas respuestas.

¿Qué tal esta función, o incluso más simple si reestructura los datos JSON?

function getData(JsonString: String; User: String; Field: String): String;
var
  JSonValue: TJSonValue;
  JsonArray: TJSONArray;
  ArrayElement: TJSonValue;
  FoundValue: TJSonValue;
begin
  Result :='';

  // create TJSonObject from string
  JsonValue := TJSonObject.ParseJSONValue(JsonString);

  // get the array
  JsonArray := JsonValue as TJSONArray;

  // iterate the array
  for ArrayElement in JsonArray do begin
      FoundValue := ArrayElement.FindValue(User);
      if FoundValue <> nil then begin
        Result := ArrayElement.GetValue(User + '.' + Field);
        break;
      end;
  end;
end;

El problema con el código JSON de muestra anterior es que utiliza los nombres de los usuarios “a” “b” como JSON-key key: data para los datos de los usuarios. De esta manera, no puede usar GetValue (“a”) en su búsqueda de datos. Estructurar sus datos JSON de manera diferente hace que el proceso de búsqueda sea mucho más fácil. Más adelante daré un ejemplo de esto.

Una forma de manejar los datos JSON dados es usando FindValue para que pueda comprobar si un campo con key “a” o “b” existe.

FoundValue := ArrayElement.FindValue("b");
if FoundValue <> nil then begin
    Result := ArrayElement.GetValue("b"+ '.' + "email");
    break;

Acerca de ‘analizar un JSON array‘pregunta: Después de que los datos se carguen como un TJSonObject, puede cambiar los datos a un TJSONArray e iterar los elementos.

  JsonValue := TJSonObject.ParseJSONValue(JsonString);  
  JsonArray := JsonValue as TJSONArray;
  for ArrayElement in JsonArray do begin
    ...

Un código de ejemplo funcional para los datos JSON dados:

unit JsonArray1;

interface

uses System.JSON;

function getData2(JsonString: String; User: String; Field: String): String;
procedure Test1();

implementation

function getData2(JsonString: String; User: String; Field: String): String;
var
  JSonValue: TJSonValue;
  JsonArray: TJSONArray;
  ArrayElement: TJSonValue;
  FoundValue: TJSonValue;
begin
  Result :='';

  // create TJSonObject from string
  JsonValue := TJSonObject.ParseJSONValue(JsonString);

  // get the array
  JsonArray := JsonValue as TJSONArray;

  // iterate the array
  for ArrayElement in JsonArray do begin
      FoundValue := ArrayElement.FindValue(User);
      if FoundValue <> nil then begin
        Result := ArrayElement.GetValue(User + '.' + Field);
        break;
      end;
  end;
end;

procedure Test1();
var
  DataBase: String;
  EmailAddress : String;
  Username: String;
begin
  DataBase := '[  "a" : "username":"aaa","email":"[email protected]",' +
                 '"b" : "username":"bbb","email":"[email protected]"  ]';

  EmailAddress := getData2(DataBase, 'b', 'email');
  Username := getData2(DataBase, 'a', 'username');

end;

end.

Como ya se mencionó, la reestructuración de los datos JSON con las keys hace que el código para encontrar datos sea más simple. Debido a que existe una relación de 1 a 1 entre los datos de los usuarios “a”: , “b”: es fácil presentar un “usuario” key. También agregando un ‘usuarios’ key al array da como resultado que todos los datos tengan keys.

  '"users" : [ "user":"a", "username":"aaa","email":"[email protected]",' +
              ' "user":"b", "username":"bbb","email":"[email protected]"]';

Cuando itera los usuarios, ahora puede usar GetValue con el nuevo “usuario” key.

  if ArrayElement.GetValue('user') = 'b' then begin
    Result := ArrayElement.GetValue('email');

Al dar el array a key ahora puedes conseguir el array con:

JsonArray := JsonValue.GetValue('users');

Un código de ejemplo funcional para los datos JSON reestructurados:

unit JsonArray2;

interface

uses System.JSON;

function getData2(JsonString: String; User: String; Field: String): String;
procedure Test2();

implementation

function getData2(JsonString: String; User: String; Field: String): String;
var
  JSonValue: TJSonValue;
  JsonArray: TJSONArray;
  ArrayElement: TJSonValue;
  FoundValue: TJSonValue;
begin
  Result :='';

  // create TJSonObject from string
  JsonValue := TJSonObject.ParseJSONValue(JsonString);

  // get the array
  JsonArray := JsonValue.GetValue('users');

  // iterate the array
  for ArrayElement in JsonArray do begin
      if ArrayElement.GetValue('user') = User then begin
        Result := ArrayElement.GetValue(Field);
        break;
      end;
  end;
end;

procedure Test2();
var
  DataBase: String;
  EmailAddress : String;
  Username: String;
begin
  DataBase := '"users" : [ "user":"a", "username":"aaa","email":"[email protected]",' +
                          ' "user":"b", "username":"bbb","email":"[email protected]"]';

  EmailAddress := getData2(DataBase, 'b', 'email');
  Username := getData2(DataBase, 'a', 'username');

end;

end.

Tu JSON es un array de objetos, entonces FIds es un TJSONArray conteniendo TJSONObject elementos. Y el a y b los campos de esos objetos son en sí mismos objetos, no matrices. Entonces FValue is TJSONArray siempre será false mientras enumera eso array.

También, (FValue as TJSONArray).Items[0] as TJSONValue).Value = name es incorrecto, porque un objeto JSON contiene pares de nombre / valor, pero está ignorando los nombres y está tratando de enumerar los pares como si fueran elementos de un array cuando en realidad no lo son. Si desea enumerar los pares de un objeto, utilice el TJSONObject.Count y TJSONObject.Pairs[] propiedad. Pero eso no es necesario en esta situación ya que está buscando un par específico por su nombre. TJSONObject tiene un Values[] propiedad para ese mismo propósito.

Y TJSONObject.ParseJSONValue(((FValue as TJSONArray).Items[0] as TJSONValue).ToJSON) as TJSONArray es simplemente ridículo. No hay ninguna razón para volver a convertir un objeto a JSON string solo para analizarlo nuevamente. Ya se ha analizado una vez, no es necesario volver a analizarlo.

Y por último, FValueInner.GetValue(data) está mal, porque TJSONValue no tiene una GetValue() método, y mucho menos uno que usa genéricos.

Ahora, dicho esto, intente algo más como esto en su lugar:

// 'name' can be 'a' or 'b'  | 'data' can be 'username' or 'email'
function TTest.getData(const name, data: string): string;
var
  FValue, FValueInner: TJSONValue;
begin
  Result := '';
  for FValue in Fids do
  begin
    if (FValue is TJSONObject) then
    begin
      FValueInner := TJSONObject(FValue).Values[name];
      if FValueInner <> nil then
      begin
        if (FValueInner is TJSONObject) then
        begin
          FValueInner := TJSONObject(FValueInner).Values[data]; 
          if FValueInner <> nil then
            Result := FValueInner.Value;
        end;
        Exit;
      end;
    end;
  end;
end;

Aquí puedes ver las comentarios y valoraciones de los lectores

Al final de todo puedes encontrar las interpretaciones de otros sys admins, tú además tienes la opción de mostrar el tuyo si lo deseas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *