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
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.