Raffaele Rossi
Raffaele Rossi

Reputation: 3147

Delphi JsonTextReader fails to read values

I have a very weird situation.

This is the JSON I am trying to parse:

[
  {
    "username":"xxx",
    "email":"[email protected]",
    "custom_title":"xxx title",
    "timezone":"Africa\/Cairo",
    "message_count":"218",
    "alerts_unread":"0",
    "like_count":"385",
    "friend_count":"0"
  }
]

This is my parsing code:

type
  TUserData = record
    email, timezone: string;
    msg, alerts, likes: integer;
 end;

procedure TDMRest.parseData(var b: TUserData);
var
  jtr: TJsonTextReader;
  sr: TStringReader;
begin
  //RESTResponseLogin.Content has the above json text
  sr := TStringReader.Create(RESTResponseLogin.Content);
  try
    jtr := TJsonTextReader.Create(sr);
    try
      while jtr.Read do
      begin
        if jtr.TokenType = TJsonToken.StartObject then
          process(b, jtr);
      end;
    finally
      jtr.Free;
    end;
  finally
    sr.Free;
   end;
end;

//here there is a problem
procedure TDMRest.process(var c: TUserData; jtr: TJsonTextReader);
begin
  while jtr.Read do
  begin
    if (jtr.TokenType = TJsonToken.PropertyName) then
    begin
      if jtr.Value.ToString = 'email' then
      begin
        jtr.Read;
        c.email := jtr.Value.AsString;
      end;

      if jtr.Value.ToString = 'timezone' then
      begin
        jtr.Read;
        c.timezone := jtr.Value.AsString;
      end;

      if jtr.Value.ToString = 'message_count' then
      begin
        jtr.Read;
        c.msg := jtr.Value.AsInteger;
      end;

      if jtr.TokenType = TJsonToken.EndObject then
      begin
        c.alerts := 0;
        c.likes := 0;
        exit;
      end;
    end;
  end;
end;

MY PROBLEM: In the process() code, the first 2 if blocks (email and timezone) can read values into my record. But when I add other if blocks (like if jtr.Value.ToString = 'message_count' then), I cannot see the values of my record anymore.

Am I parsing the data properly?

Basically, I need to grab the info from a JSON string and put the data inside a TUserData record.

I have found the above pattern in a book titled "Expert Delphi", and I am pretty sure that the parseData() function is correct. Probably I am missing something in the process.

The TDMRrst is a DataModule; I am giving the function a record, and I'd like the data to be properly parsed.

What is wrong here?

Upvotes: 2

Views: 930

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 598414

In the JSON you have shown, all of the values are strings, there are no integers. So, when you call jtr.Value.AsInteger for the message_count value, it raises a conversion exception that you are not catching. TValue.AsInteger DOES NOT perform an implicit conversion from string to integer for you.

You will have to use jtr.Value.AsString instead and convert the string to an integer using StrToInt():

if jtr.Value.ToString = 'message_count' then
begin
  jtr.Read;
  //c.msg := jtr.Value.AsInteger;
  c.msg := StrToInt(jtr.Value.AsString);
end;

Do the same for the other "integer" values in the JSON (alerts_unread, like_count, and friend_count).

Upvotes: 3

Related Questions