Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 10 of 10 total
Thread TStringList and JSON string with CR + LF
Fri, Mar 17 2017 5:39 AMPermanent Link

thomh

Hello,

I have my server sending a JSON string which contains line feed and carriage returns. I have escaped them and they are returned to EWB like this:

"Comments": "This is a comment.\\r\\nWith another line.\\r\\nAnd another line."

When I load this string into a TStringList using the Text property I get:

"This is a comment.\r\nWith another line.\r\nAnd another line."

How do I load this string into a EWB TStringList so that it understands the line feed and carriage returns?

Thanks.

// Thom
Fri, Mar 17 2017 6:06 AMPermanent Link

Uli Becker

> How do I load this string into a EWB TStringList so that it understands the line feed and carriage returns?

That's what I use:

procedure TMainForm.Button1Click(Sender: TObject);
var
   sl: TStringList;
   s: string;
begin
   s := 'This is a comment.\\r\\nWith another line.\\r\\nAnd another
line.';
   sl := TStringList.create;
   PopulateStringList(sl,s,'\\r\\n');
end;

procedure TMainForm.PopulateStringList(FStringList: TStringList; FText,
FLFCR: string);
var
   Temp: Array of String;
   i: integer;
begin
   Temp := Split(FText,FLFCR);
   FStringList.clear;
   for i := 0 to Length(Temp)-1 do
      FStringList.Add(Temp[i]);
end;

Uli
Fri, Mar 17 2017 6:47 AMPermanent Link

Matthew Jones

thomh wrote:

> How do I load this string into a EWB TStringList so that it understands the line feed and carriage returns?

Hmm, the JSON standard should support this, and so I have a slightly modified webcore file (just copied the lines in the beta for testing).

In UnEscapeStr:

   case Chars[I] of
   BACKSLASH,DOUBLE_QUOTE,SLASH:
      Remove(I-1,1);
// new
   'n':    
   begin
      Remove(I-1,1);
      Chars[I] := #13; // #10;
   end;
   't':
   begin
      Remove(I-1,1);
      Chars[I] := #9; // #10;
   end;
   'r':
   begin
      Remove(I-1,1);
      Chars[I] := #13; // #10;
   end;
// back to existing
   ESCAPE_UNICODE:
   begin


In TParser.ParseString:

case FText[FPos] of
 BACKSLASH,DOUBLE_QUOTE,SLASH:
    begin
    FTokenString:=(FTokenString+FText[FPos]);
    Inc(FPos);
    end;
// new
 'n':
    begin
    FTokenString:=(FTokenString+#13);
    Inc(FPos);
    end;
 't':
    begin
    FTokenString:=(FTokenString+#9);
    Inc(FPos);
    end;
 'r':
    begin
    FTokenString:=(FTokenString+#13);
    Inc(FPos);
    end;
// back to existing
 ESCAPE_UNICODE:


This is now fully compatible with the .Net generated output that I am getting from my server.

--

Matthew Jones
Fri, Mar 17 2017 8:20 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

<< Hmm, the JSON standard should support this, and so I have a slightly modified webcore file (just copied the lines in the beta for testing). >>

I've modified the UnEscapeStr function to handle these also.  The EscapeStr is less ambiguous (/n can mean different things on different platforms) and uses the Unicode escape character for all control characters.

However, I think your modifications are slightly off.  Here's what I came up with:

function UnEscapeStr(const Value: String): String;
var
  I: Integer;
  J: Integer;
  TempStringBuilder: TStringBuilder;
  TempString: String;
begin
  TempStringBuilder:=TStringBuilder.Create(Value);
  try
     with TempStringBuilder do
        begin
        I:=0;
        while (I < TempStringBuilder.Length) do
           begin
           if (Chars[I]=BACKSLASH) then
              begin
              if (I < Length) then
                 begin
                 Inc(I);
                 case Chars[I] of
                    BACKSLASH,DOUBLE_QUOTE,SLASH:
                       Remove(I-1,1);
                    ESCAPE_BACKSPACE:
                       begin
                       Chars[I]:=BACKSPACE;
                       Remove(I-1,1);
                       end;
                    ESCAPE_TAB:
                       begin
                       Chars[I]:=TAB;
                       Remove(I-1,1);
                       end;
                    ESCAPE_CR:
                       begin
                       Chars[I]:=CR;
                       Remove(I-1,1);
                       end;
                    ESCAPE_LF:
                       begin
                       Chars[I]:=LF;
                       Remove(I-1,1);
                       end;
                    ESCAPE_CRLF:
                       begin
                       Chars[I-1]:=CR;
                       Chars[I]:=LF;
                       end;
                    ESCAPE_UNICODE:
                       begin
                       Remove(I-1,1);
                       J:=I;
                       TempString:='';
                       while (J < Length) and (J < (I+4)) do
                          begin
                          TempString:=TempString+Chars[J];
                          Inc(J);
                          end;
                       Chars[I-1]:=Chr(StrToInt('0x'+TempString));
                       Remove(I,Length(TempString));
                       end;
                    end;
                 end;
              end
           else
              Inc(I);
           end;
        Result:=ToString;
        end;
  finally
     TempStringBuilder.Free;
  end;
end;

Tim Young
Elevate Software
www.elevatesoft.com
Fri, Mar 17 2017 11:20 AMPermanent Link

thomh

Thanks, guys.

I tried to incorporate Tim's code into the WebCore unit but when I opened EWB it failed on ESCAPE_BACKSPACE. I guess I am missing some constants.

// Thom
Fri, Mar 17 2017 11:54 AMPermanent Link

Matthew Jones

Tim Young [Elevate Software] wrote:

> However, I think your modifications are slightly off.

They may be, but they work well enough for me and popping into the edit boxes. I'll await your next update and apply that.

--

Matthew Jones
Fri, Mar 17 2017 1:06 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

<< They may be, but they work well enough for me and popping into the edit boxes. >>

I'll have to test them, but they shouldn't work at all - it looks to me like you're setting the character at the wrong position - the Remove() calls will cause the current position to move backward by one.

Tim Young
Elevate Software
www.elevatesoft.com
Fri, Mar 17 2017 1:13 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Thom,

<< I tried to incorporate Tim's code into the WebCore unit but when I opened EWB it failed on ESCAPE_BACKSPACE. I guess I am missing some constants. >>

Sorry, here you go:

  ESCAPE_BACKSPACE = 'b';
  ESCAPE_TAB = 't';
  ESCAPE_CR = 'r';
  ESCAPE_LF = 'f';
  ESCAPE_CRLF = 'n';

And, here's a revised version of the function that deals with the character position incrementing in a more straightforward manner:

function UnEscapeStr(const Value: String): String;
var
  I: Integer;
  J: Integer;
  TempStringBuilder: TStringBuilder;
  TempString: String;
begin
  TempStringBuilder:=TStringBuilder.Create(Value);
  try
     with TempStringBuilder do
        begin
        I:=0;
        while (I < TempStringBuilder.Length) do
           begin
           if (Chars[I]=BACKSLASH) then
              begin
              if (I < Length) then
                 begin
                 Inc(I);
                 case Chars[I] of
                    BACKSLASH,DOUBLE_QUOTE,SLASH:
                       Remove(I-1,1);
                    ESCAPE_BACKSPACE:
                       begin
                       Remove(I-1,1);
                       Chars[I-1]:=BACKSPACE;
                       end;
                    ESCAPE_TAB:
                       begin
                       Remove(I-1,1);
                       Chars[I-1]:=TAB;
                       end;
                    ESCAPE_CR:
                       begin
                       Remove(I-1,1);
                       Chars[I-1]:=CR;
                       end;
                    ESCAPE_LF:
                       begin
                       Remove(I-1,1);
                       Chars[I-1]:=LF;
                       end;
                    ESCAPE_CRLF:
                       begin
                       Chars[I-1]:=CR;
                       Chars[I]:=LF;
                       end;
                    ESCAPE_UNICODE:
                       begin
                       Remove(I-1,1);
                       J:=I;
                       TempString:='';
                       while (J < Length) and (J < (I+4)) do
                          begin
                          TempString:=TempString+Chars[J];
                          Inc(J);
                          end;
                       Chars[I-1]:=Chr(StrToInt('0x'+TempString));
                       Remove(I,Length(TempString));
                       end;
                    end;
                 end;
              end
           else
              Inc(I);
           end;
        Result:=ToString;
        end;
  finally
     TempStringBuilder.Free;
  end;
end;

Tim Young
Elevate Software
www.elevatesoft.com
Tue, Mar 21 2017 11:58 AMPermanent Link

Matthew Jones

Tim Young [Elevate Software] wrote:

> function UnEscapeStr(const Value: String): String;

You haven't done the ParseString matches too, at least not in the latest Beta.

--

Matthew Jones
Tue, Mar 21 2017 12:46 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

<< You haven't done the ParseString matches too, at least not in the latest Beta. >>

Thanks.  Build 7 has them now.

Tim Young
Elevate Software
www.elevatesoft.com
Image