Thursday, March 21, 2019

Delphi JSON parsing

you can transform the JSON string representation into a JSON with one of the following code snippets.
Using ParseJSONValue:

procedure CreateJsonString;
var
  LJSONObject: TJSONObject;
 const
  JSONString =
    '{' +
    '    "name": {'+
    '        "A JSON Object": {' +
    '          "id": "1"' +
    '        },' +
    '        "Another JSON Object": {' +
    '          "id": "2"' +
    '        }' +
    '    },' +
    '    "totalobjects": "2"' +
    '}';
begin LJSONObject := nil; try { convert String to JSON } LJSONObject := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(JSONString), 0) as TJSONObject; { output the JSON to console as String } Writeln(LJSONObject.ToString); finally LJSONObject.Free; end;
Using Parse:
procedure ConsumeJsonBytes;
var
  LJSONObject: TJSONObject;

begin
  LJSONObject := nil;
  try
    LJSONObject := TJsonObject.Create;
    { convert String to JSON }
    LJSONObject.Parse(BytesOf(GJSONString), 0);

    { output the JSON to console as String }
    Writeln(LJSONObject.ToString);
  finally
    LJSONObject.Free;
  end;
end;
TJSONObject.ParseJSONValue() returns a nil pointer if parsing fails. Embarcadero's example does not check for that condition. If parsing failed, that would account for the "invalid type cast" error being raised by the as operator.
TJSONObject.Parse() returns -1 if parsing fails. Embarcadero's example does not check for that condition.
Because TJSONObject parses bytes, not characters, I suggest you not use TFile.ReadAllText(), which will read bytes and decode them to UTF-16 using TEncoding.Default if the file does not have have a BOM. In your particular example, that is not an issue since your JSON contains only ASCII characters. But that can be an issue if non-ASCII Unicode characters are used. JSON uses UTF-8 by default (which is why the IsUTF8 parameter of TJSONObject.ParseJSONValue() is true by default).
In any case, your code does not match the structure of the JSON data you have shown. Your JSON data is an array of objects, so the first item parsed will be a TJSONArray, not a TJSONObject. If you use TSJONObject.ParseJSONValue(), it will return a TJSONValue that can be type-casted to TJSONArray:
procedure TfMain.loadScenarioData(aFilename: string);
var
  vJSONBytes: TBytes;
  vJSONScenario: TJSONObject;
  vJSONArray: TJSONArray;
  vJSONValue: TJSONValue;
  vJSONObject: TJSONObject;
  vJSONPair: TJSONPair;
  vJSONScenarioEntry: TJSONString;
  vJSONScenarioValue: string;
  vParseResult: Integer;
begin
  vJSONBytes := TFile.ReadAllBytes(aFileName);

  vJSONScenario := TJSONObject.Create;
  try
    vParseResult := vJSONScenario.Parse(vJSONBytes, 0);
    if vParseResult >= 0 then
    begin
      //BetFair Specific 'caption' key
      vJSONArray := vJSONScenario.Get(0) as TJSONArray;
      for vJSONValue in vJSONArray do
      begin
        vJSONObject := vJSONValue as TJSONObject;
        vJSONPair := vJSONObject.Get('caption');
        vJSONScenarioEntry := vJSONPair.JsonString;
        vJSONScenarioValue := vJSONScenarioEntry.Value;
        cbScenario.Items.Add(vJSONScenarioValue);
      end;
    end;
  finally
    vJSONScenario.Free;
  end;
end;

1 comment:

Mefisto said...

How may I to do for cast a TByteDynArray (soap) to Json?
I get truncated string ever

Delphi Thread Example

Delphi Thread Example Threads mean a lot with the latest computer technology. They allow you to perform multiple tasks at the same time ...