I need to parse the below JSON response from a Firebase Database. In this JSON sample, there are 2 documents qouap9
and 15p3vl
. Both documents have multiple fields. I want to merge all of the fields' strings from each document to one line.
{
"documents": [
{
"name": "projects/..",
"fields": {
"qouap9": {
"stringValue": "A1:Hello;"
},
"5": {
"stringValue": "A9:..."
},
"6": {
"stringValue": "A10:..."
}
},
"createTime": "2020-08-08T20:44:2",
"updateTime": "2020-08-08T20:44:3"
},
{
"name": "projects/..",
"fields": {
"15p3vl": {
"stringValue": "A2:2020;"
},
"2": {
"stringValue": "A6:..."
},
"t0w4yj": {
"stringValue": "A4:2020;"
},
"1": {
"stringValue": "A5:..."
}
},
"createTime": "2020-10-20T06:58:2",
"updateTime": "2020-10-20T06:58:2"
}
]
}
I want the result to be like this :
A1:Hello; A9:... A10:...
A2:2020; A6:... A4:2020; A5:...
CodePudding user response:
Since last time I did not explain enough, here is another try.
implementation
uses
System.JSON;
procedure DoSomeJSONStuff(const jsonstr: string);
var
jo, fields: TJSONObject;
ja: TJSONArray;
jv: TJSONValue;
i: integer;
desiredstr: string;
begin
// 1.
jo := TJSONObject.ParseJSONValue(jsonstr) as TJSONObject;
if (jo <> nil) then begin
try
// 2.
ja := jo.GetValue('documents') as TJSONArray;
// 3.
for jv in ja do begin
fields := (jv as TJSONObject).GetValue('fields') as TJSONObject;
desiredstr := '';
// 4.
for i := 0 to fields.Count - 1 do begin
desiredstr := desiredstr (fields.Pairs[i].JsonValue as TJSONObject).GetValue('stringValue').Value;
end;
ShowMessage(desiredstr);
end;
finally
// 5.
jo.Free;
end;
end;
end;
In
jsonstr
is your JSON as a string. WithTJSONObject.ParseJSONValue
you can parse your JSON and get aTJSONValue
back if it does not fail. Otherwise the value isnil
, hence the check forvariable <> nil
. SinceTJSONObject
is derived fromTJSONValue
, it can simply be cast explicitly in this case. Almost everything is derived fromTJSONValue
in the Delphi JSON framework. If you want to check if theTJSONValue
is really your desired JSON container you could do it like this:var jv: TJSONValue; jo: TJSONObject; begin jv := TJSONObject.ParseJSONValue(jsonstr); if jv is TJSONObject then begin jo := (jv as TJSONObject); // code here end else raise Exception.Create('Unexpected container - expected: TJSONObject');
The next step is to get the
documents
in your JSON. The value of that is an array. If you're not sure about the structure you could useTryGetValue
instead ofGetValue
. You could check again if the returned value is actually aTJSONArray
withvariable is TJSONArray
. I assume your structure is always the same.Now we iterate through the array with a simple
for in
loop.Since the element names of your
fields
do not have a "static" name we iterate through the fields by count. We get theTJSONValue
and cast it as aTJSONObject
. And for theTJSONObject
we get thestringValue
s withGetValue('stringValue').Value
and concatenate it to thedesirestr
variable.You only have to free your "main" variable/container as long as you only reference to it. Everything else is just a
Pointer
.
Edit #1: Hint about nil. Edit #2: Free memory.