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
jsonstris your JSON as a string. WithTJSONObject.ParseJSONValueyou can parse your JSON and get aTJSONValueback if it does not fail. Otherwise the value isnil, hence the check forvariable <> nil. SinceTJSONObjectis derived fromTJSONValue, it can simply be cast explicitly in this case. Almost everything is derived fromTJSONValuein the Delphi JSON framework. If you want to check if theTJSONValueis 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
documentsin your JSON. The value of that is an array. If you're not sure about the structure you could useTryGetValueinstead ofGetValue. You could check again if the returned value is actually aTJSONArraywithvariable is TJSONArray. I assume your structure is always the same.Now we iterate through the array with a simple
for inloop.Since the element names of your
fieldsdo not have a "static" name we iterate through the fields by count. We get theTJSONValueand cast it as aTJSONObject. And for theTJSONObjectwe get thestringValues withGetValue('stringValue').Valueand concatenate it to thedesirestrvariable.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.
