2016年2月

首页2016年2月
25
Feb
0

关于内存数据与SYSTEM.JSON单元

闲话:

正在用 WebBroker 写一个小网站,感受颇多:
1、如果是写一个小东西,应该先考虑下 WebBroker,因为它是分分钟即可上手的。
2、如果要写一个大东西,或许也应该考虑下 WebBroker,因为相比其他它有着最高的灵活度(但这只是想像,因为我只是写了一个小东西)。
3、Delphi 3 就有了 WebBroker,可惜现在才开始使用它;随着“服务器”与“网页程序”的普及,WebBroker 应该会被更多地提起。

期间用到了 json, 所以有了这篇博文。

Delphi 与内存数据的总结与回顾:

1、普通类型变量:储存一个数据。

2、数组:储存一组同类型的数据。

3、结构体:储存一组不同类型的数据;现在的结构体越来越复杂了,还可以操作这些个数据,越来越像“类”了。

4、“键值”对:我一般使用 TStringList,并常常用它代替 ini 文件类;同类还有 THashedStringList、TStringHash。

5、分类的 “键值”对:TMemIniFile、TIniFile; 另外还有人用 sqlite 做了一个可以储存二进制数据的 ini 文件类(忘了名了),我试过,非常好用(在官方示例中)。

6、内存数据表:现在应该首选 TFDMemTable 了(之前是 TClientDataSet)。

7、数据库级别的内存(或文件)数据:SqLite。

8、内存多叉树:JSON(或 XML);之前一直使用 SuperObject,以后会使用 System.JSON 更多些。

System.JSON?还是 SuperObject?

System.JSON 是官方的;这省去很多麻烦,这也是我考虑它的主要原因。

System.JSON “读写文件” 与 “格式化” 等功能,都有的功能也不如 SuperObject 方便。

System.JSON 主要考虑的是:从服务器生成 json,然后传输到客户端(特别是给 JavaScript 使用),不像 SuperObject 大而全。

如果不是太复杂的 json 应用,优先考虑 System.JSON 吧;如果需要更多功能,SuperObject 会更理想。

1 分钟了解 System.JSON:

其中的类不少,主要用到的有:TJSONObject、TJSONArray。

uses System.JSON;

//TJSONObject
procedure TForm1.Button1Click(Sender: TObject);
var
j: TJSONObject;
begin
j := TJSONObject.Create;
j.AddPair('aa', '111');
j.AddPair('bb', '222');

//输出字符串
Memo1.Text := j.ToString; //结果:{"aa":"111","bb":"222"}

{ToJSON 与 ToString 结果相同,但应尽量使用 ToString 而不是 ToJSON;因为 ToJSON 也是调用 ToString 并且还要重新分配内存}

j.Free;
end;

//TJSONArray
procedure TForm1.Button2Click(Sender: TObject);
var
a: TJSONArray;
begin
a := TJSONArray.Create;
a.Add(1); //TJSONArray 不像传统的数组,它可以接受几种不同类型的值;这应该算是对 Delphi 数组功能的扩充吧。
a.Add(2);
a.Add('aaa');
a.Add('bbb');

Memo1.Text := a.ToString; //结果:[1,2,"aaa","bbb"]

a.Free;
end;

//当 TJSONObject 嵌套其他对象时
procedure TForm1.Button3Click(Sender: TObject);
var
j: TJSONObject;
a: TJSONArray;
begin
j := TJSONObject.Create;
a := TJSONArray.Create('aaa', 'bbb'); //可以使用两个值初始化
a.Add(1);
a.Add(2);

j.AddPair('arr', a);

Memo1.Text := j.ToString; //结果:{"arr":["aaa","bbb",1,2]}

// a.Free; {千万不要释放其内部对象,它的父对象会自动释放它}
j.Free;
end;

//变通上例
procedure TForm1.Button4Click(Sender: TObject);
var
j: TJSONObject;
begin
j := TJSONObject.Create;

j.AddPair('arr', TJSONArray.Create);

with j.Values['arr'] as TJSONArray do
begin

Add('aaa');
Add('bbb');
Add(1);
Add(2);

end;

Memo1.Text := j.ToString; //结果:{"arr":["aaa","bbb",1,2]}
j.Free;
end;

//再变通
procedure TForm1.Button5Click(Sender: TObject);
var
j: TJSONObject;
a: TJSONArray;
begin
j := TJSONObject.Create;

j.AddPair('arr', TJSONArray.Create);

a := TJSONArray(j.Values['arr']);
a.Add('aaa');
a.Add('bbb');
a.Add(1);
a.Add(2);

Memo1.Text := j.ToString; //结果:{"arr":["aaa","bbb",1,2]}
j.Free;
end;

//添加其他类型的数
procedure TForm1.Button6Click(Sender: TObject);
var
j: TJSONObject;
a: TJSONArray;
begin
j := TJSONObject.Create;
j.AddPair('数值', TJSONNumber.Create(3.1415926));
j.AddPair('布尔真', TJSONTrue.Create);
j.AddPair('布尔假', TJSONFalse.Create);
j.AddPair('空值', TJSONNull.Create);

Memo1.Text := j.ToString; //结果:{"数值":3.1415926,"布尔真":true,"布尔假":false,"空值":null}
j.Free;
end;

//读取
procedure TForm1.Button7Click(Sender: TObject);
var
j: TJSONObject;
str: string;
num: Integer;
arr1,arr2: string;
begin
j := TJSONObject.Create;
j.AddPair('str', '111');
j.AddPair('num', TJSONNumber.Create(222));
j.AddPair('arr', TJSONArray.Create('arr1', 'arr2'));

Memo1.Text := j.ToString; //结果:{"str":"111","num":222,"arr":["arr1","arr2"]}

//JSON 是一组”键值对“,其中的”值“还有可能是”键值对“;
//所以 System.JSON 用 TJSONValue 来表示值类型,它是所有值类型的父类,当然也是 TJSONObject 的父类。

str := j.Values['str'].Value; //Values[] 调用的是 GetValue(), 更喜欢直接用后者
num := j.GetValue('num').Value.ToInteger;

arr1 := TJSONArray(j.GetValue('arr')).Items[0].Value;
arr2 := TJSONArray(j.GetValue('arr')).Items[1].Value;

Memo1.Lines.Add(Format('%s, %d, %s, %s', [str, num, arr1, arr2])); //111, 222, arr1, arr2

j.Free;
end;

//遍历
procedure TForm1.Button8Click(Sender: TObject);
var
j: TJSONObject;
p: TJSONPair;
v: TJSONValue;
i: Integer;
a: TJSONArray;
begin
j := TJSONObject.Create;
j.AddPair('aa', '111');
j.AddPair('bb', '222');
j.AddPair('arr', TJSONArray.Create('arr1', 'arr2'));

//集合遍历 TJSONObject
for p in j do

Memo1.Lines.Add(p.ToString); //"aa":"111" \\ "bb":"222" \\ "arr":["arr1","arr2"]

//索引遍历 TJSONObject, 这里的 Get 函数已不提倡使用了
for i := 0 to j.Count - 1 do

Memo1.Lines.Add(j.Get(i).ToString); //"aa":"111" \\ "bb":"222" \\ "arr":["arr1","arr2"]

//集合遍历 TJSONArray
for v in j.Values['arr'] as TJSONArray do

Memo1.Lines.Add(v.Value); //arr1 \\ arr2

//索引遍历 TJSONArray
a := j.Values['arr'] as TJSONArray;
for i := 0 to a.Count - 1 do

Memo1.Lines.Add(a.Items[i].Value); //arr1 \\ arr2

j.Free;
end;

//存取到文件
procedure TForm1.Button9Click(Sender: TObject);
var
j1,j2: TJSONObject;
begin
//随便虚拟些数据
j1 := TJSONObject.Create(TJSONPair.Create('aaa', '111'));
j1.AddPair('bbb', j1.Clone as TJSONValue);

ChDir('c:temp');

//写入文件
with TStringList.Create do
begin

Add(j1.ToString);
SaveToFile('JsonTest.txt', TEncoding.UTF8); //结果:{"aaa":"111","bbb":{"aaa":"111"}}
Free;

end;
j1.Free;

//从文件读取
with TStringList.Create do
begin

LoadFromFile('JsonTest.txt', TEncoding.UTF8);
j2 := TJSONObject.ParseJSONValue(Text) as TJSONObject;
Free;

end;

Memo1.Text := j2.ToString; //结果:{"aaa":"111","bbb":{"aaa":"111"}}
j2.Free;
end;

//修改、删除
procedure TForm1.Button10Click(Sender: TObject);
var
j: TJSONObject;
begin
j := TJSONObject.Create;
j.AddPair('aaa', '111');
j.AddPair('bbb', '222');
j.AddPair('ccc', '333');

//修改
j.Get('aaa').JsonValue := TJSONString.Create('11111'); //TJSONPair 的 JsonString、JsonValue 分别是 键、值
// j.Pairs[0].JsonValue := TJSONString.Create('11111');

//删除
j.RemovePair('bbb');

Memo1.Lines.Add(j.ToString); //结果:{"aaa":"11111","ccc":"333"}

j.Free;
end;

//根据路径添加数组的函数:
procedure CreateJSONPathArr(aJson: TJSONObject; const aPath: string; jArr: TJSONArray);
var
arr: TArray<string>;
path: string;
i: Integer;
begin
arr := aPath.Split(['.'], ExcludeEmpty);
for i := 0 to Length(arr) - 1 do
begin

if not aJson.TryGetValue(arr[i], aJson) then
begin
  if i = Length(arr) - 1 then
    aJson.AddPair(arr[i], jArr)
  else begin
    aJson.AddPair(arr[i], TJSONObject.Create);
    aJson.TryGetValue(arr[i], aJson);
  end;
end;

end;
end;

//调用测试:
var
j: TJSONObject;
a: TJSONArray;
begin
j := TJSONObject.Create;

a := TJSONArray.Create('11', '22');
CreateJSONPathArr(j, 'aaa.bbb.ccc', a);

a := TJSONArray.Create('33', '44');
CreateJSONPathArr(j, 'aaa.bbb.ddd', a);

j.Free;
end;

24
Feb
0

DELPHI用原生WinINet.DLL调用HTTPS

///下网页
function PostData(url, data, Len, Auth: string):string;
var
hInt, hConn, hreq: HINTERNET;
buffer: PChar;
dwRead, dwFlags: cardinal;
port: Word;
uri: TIdURI;
proto, host, path: string;
header:string;
res :TStringStream;
IsSue:LongBool;
ErrorNum:Integer;
value: DWORD;
begin
res := TStringStream.Create;
try

uri := TIdURI.Create(url);
try
  host := uri.Host;
  path := uri.Path + uri.Document + uri.Params;
  proto := uri.Protocol;
finally
  FreeAndNil(uri);
end;
if UpperCase(proto) = 'HTTPS' then
begin
  port := INTERNET_DEFAULT_HTTPS_PORT;
  dwFlags := INTERNET_FLAG_SECURE;
end
else
begin
  port := INTERNET_INVALID_PORT_NUMBER;
  dwFlags := INTERNET_FLAG_RELOAD;
end;
hInt := InternetOpen('Delphi', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
hConn := InternetConnect(hInt, PChar(host), port, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);
hreq := HttpOpenRequest(hConn, 'POST', PChar(Path), 'HTTP/1.1', nil, nil, dwFlags, 0);
GetMem(buffer, 65536);
try
  header:='Content-Length:'+len+
          #13'Accept:application/json'+
          #13'Content-Type:application/json'+
          #13'Authorization:'+auth +
          #13'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)'+
          #13'Connection:close';
  IsSue := HttpSendRequestW(hReq, PWideChar(header), Length(header), PChar(UTF8Encode(data)), Length(UTF8Encode(data)));
  if IsSue then
  begin
    dwRead := 0;
    repeat
      InternetReadFile(hreq, buffer, 65536, dwRead);
      if dwRead <> 0 then
        res.Write(buffer^, dwRead);
    until dwRead = 0;
  end
  else
  begin
    ErrorNum := GetLastError();
  end;
  InternetCloseHandle(hreq);
  InternetCloseHandle(hConn);
  InternetCloseHandle(hInt);
finally
  FreeMem(buffer);
end;
res.Position := 0;
Result := UTF8ToString( res.DataString);

finally

FreeAndNil(res);

end;
end;
////下图片
function DownQRCodeImg(url: string;aDataStream:TMemoryStream):Boolean;
var
hInt,hConn,hreq:HINTERNET;
buffer:PChar;
dwRead, dwFlags:cardinal;
port: Word;
uri: TIdURI;
proto, host, path: string;
begin
Result := False;
uri := TIdURI.Create(url);
host := uri.Host;
path := uri.Path + uri.Document;
proto := uri.Protocol;
uri.Free;
if UpperCase(proto) = 'HTTPS' then
begin

port := INTERNET_DEFAULT_HTTPS_PORT;
dwFlags := INTERNET_FLAG_SECURE;

end
else
begin

port := INTERNET_INVALID_PORT_NUMBER;
dwFlags := INTERNET_FLAG_RELOAD;

end;
Path := Copy(url,pos('/upay/',url),maxint);
hInt := InternetOpen('Delphi',INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
hConn := InternetConnect(hInt,PChar(host),port,nil,nil,INTERNET_SERVICE_HTTP,0,0);
hreq := HttpOpenRequest(hConn,'POST',PChar(Path),'HTTP/1.1',nil,nil,dwFlags,0);
GetMem(buffer, 655360000);
if HttpSendRequest(hReq,nil,0,nil,0) then
begin

dwRead:=0;
repeat
  InternetReadFile(hreq,buffer,655360000,dwRead);
  if dwRead<>0 then
    aDataStream.Write(buffer^, dwRead);
until dwRead=0;

end;
InternetCloseHandle(hreq);
InternetCloseHandle(hConn);
InternetCloseHandle(hInt);
FreeMem(buffer);
Result := True;
end;
/////////////////////////////////////////////////////////////////////////////////////
interface

uses Classes, WinINet,Sysutils,windows, IDURI;

procedure Get(url: string;res: TStream); overload;
procedure Post(url, data:string;res:TStream); overload;
function Get(url: string): string; overload;
function Post(url, data: string): string; overload;

implementation

function Get(url: string): string;
var
s: TStringStream;
begin
s := TStringStream.Create('');
try

Get(url, s);
result := s.DataString;

finally

s.Free;

end;
end;

function Post(url, data: string): string;
var
s: TStringStream;
begin
s := TStringStream.Create('');
try

Get(url, s);
result := s.DataString;

finally

s.Free;

end;
end;

procedure Post(url, data:string;res:TStream);
var
hInt,hConn,hreq:HINTERNET;
buffer:PChar;
dwRead, dwFlags:cardinal;
port: Word;
uri: TIdURI;
proto, host, path: string;
begin
uri := TIdURI.Create(url);
host := uri.Host;
path := uri.Path + uri.Document;
proto := uri.Protocol;
uri.Free;
if UpperCase(proto) = 'HTTPS' then
begin

port := INTERNET_DEFAULT_HTTPS_PORT;
dwFlags := INTERNET_FLAG_SECURE;

end
else
begin

port := INTERNET_INVALID_PORT_NUMBER;
dwFlags := INTERNET_FLAG_RELOAD;

end;
hInt := InternetOpen('Delphi',INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
hConn := InternetConnect(hInt,PChar(host),port,nil,nil,INTERNET_SERVICE_HTTP,0,0);
hreq := HttpOpenRequest(hConn,'POST',PChar(Path),'HTTP/1.1',nil,nil,dwFlags,0);
GetMem(buffer, 65536);
if HttpSendRequest(hReq,nil,0,PChar(data),Length(data)) then
begin

dwRead:=0;
repeat
  InternetReadFile(hreq,buffer,65536,dwRead);
  if dwRead<>0 then
    res.Write(buffer^, dwRead);
until dwRead=0;

end;
InternetCloseHandle(hreq);
InternetCloseHandle(hConn);
InternetCloseHandle(hInt);
FreeMem(buffer);
end;

procedure Get(url: string;res: TStream);
var
hInt,hUrl:HINTERNET;
buffer:PChar;
dwRead:cardinal;
begin
GetMem(buffer, 65536);
hInt := InternetOpen('Delphi',INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
dwRead:=0;
hurl:=InternetOpenUrl(hInt,PChar(url),nil,0,INTERNET_FLAG_RELOAD,0);
repeat
InternetReadFile(hUrl,buffer,1000,dwRead);
if dwRead<>0 then

 res.Write(buffer^, dwRead);

until dwRead=0;
InternetCloseHandle(hUrl);
InternetCloseHandle(hInt);
FreeMem(buffer);
end;

end.
//======设置一下option,就能正常访问证书有问题的站点了=======
var value: DWORD;

value = SECURITY_FLAG_IGNORE_CERT_CN_INVALID or

    SECURITY_FLAG_IGNORE_CERT_DATE_INVALID or
    SECURITY_FLAG_IGNORE_UNKNOWN_CA or
    SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;

WinHttpSetOption(hreq, WINHTTP_OPTION_SECURITY_FLAGS, @value, SizeOf(value));

//================使用IdHttp 获取 HttpsURL内容 需要相关的DLL文件==========================
uses IdHTTP, IdSSLOpenSSL;

function HttpsGet(const aURL, aContentFile: string): Boolean;
var
vIdHTTP: TIdHTTP;
vSSL: TIdSSLIOHandlerSocket;
vMemory: TMemoryStream;
begin
try

vIdHTTP := TIdHTTP.Create(nil);
vSSL := TIdSSLIOHandlerSocket.Create(nil);
vMemory := TMemoryStream.Create;
try
  vIdHTTP.IOHandler := vSSL;
  vSSL.SSLOptions.Method := sslvSSLv3;
  vIdHTTP.Get(aURL, vMemory);
  vMemory.SaveToFile(aContentFile);
  Result := True;
finally
  vMemory.Free;
  vSSL.Free;
  vIdHTTP.Free;
end;

except

Result := False;

end;
end;

//=====================自定义头文件和POST DATA=================
//引用了WinINet,IDURI单元,其中CnMD5,CnBase64是认证业务需要加入的cnpack中的单元
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, CnMD5,
CnBase64,WinINet,IDURI,Dialogs, StdCtrls;

type
TForm2 = class(TForm)

Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var
Form2: TForm2;

implementation

{$R *.dfm}

procedure Post(url, data, Len, Auth: string; res: TStream);
var
hInt, hConn, hreq: HINTERNET;
buffer: PChar;
dwRead, dwFlags: cardinal;
port: Word;
uri: TIdURI;
proto, host, path: string;
header:string;
begin
uri := TIdURI.Create(url);
host := uri.Host;
path := uri.Path + uri.Document + uri.Params;
proto := uri.Protocol;
uri.Free;
if UpperCase(proto) = 'HTTPS' then
begin

port := INTERNET_DEFAULT_HTTPS_PORT;
dwFlags := INTERNET_FLAG_SECURE;

end
else
begin

port := INTERNET_INVALID_PORT_NUMBER;
dwFlags := INTERNET_FLAG_RELOAD;

end;
hInt := InternetOpen('Delphi', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
hConn := InternetConnect(hInt, PChar(host), port, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);
hreq := HttpOpenRequest(hConn, 'POST', PChar(Path), 'HTTP/1.1', nil, nil, dwFlags, 0);
GetMem(buffer, 65536);
header:='Content-Length:'+len+

#13'Accept:application/json'+
#13'Content-Type:application/json'+
#13'Authorization:'+auth;

if HttpSendRequest(hReq, PAnsiChar(header), Length(header), PChar(data), Length(data)) then
begin

dwRead := 0;
repeat
  InternetReadFile(hreq, buffer, 65536, dwRead);
  if dwRead <> 0 then
    res.Write(buffer^, dwRead);
until dwRead = 0;

end;
InternetCloseHandle(hreq);
InternetCloseHandle(hConn);
InternetCloseHandle(hInt);
FreeMem(buffer);
end;

procedure TForm2.Button1Click(Sender: TObject);
var
s: string;
sig: string;
b64: string;
t: string;
l,content: string;
Responses: TStringStream;
begin
t := formatdatetime('yyyyMMddHHnnss', Now);

sig := UpperCase(MD5Print(MD5String('123123123' + '234234234234' + t)));
Base64Encode('2221232321:' + t, b64);

content:=AnsiToUtf8('{"from":"13155555555","to":"18822225555"}');

l := IntToStr(Length(content));

Responses := TStringStream.Create('');
s := 'https://www.good.com:856/Callback?sig=' + sig + '';
Post(s, content,l,b64, Responses);

Memo1.text := Utf8ToAnsi(Responses.DataString);
Responses.Free;
end;

end.

24
Feb
0

Delphi XE7中使用JSON

Delphi XE7有一个对JSON处理的单元,在你需要使用JSON的单元里面引入"System.json",随后你就可以用Delphi自己的json处理类了。我写的小例子只是对包含字符串和数组的JSON进行解析,这两种数据类型,我觉得是实际使用中最常用、有用的类型,所以我仅仅用这两种例子做演示!
{

功能:DelphiXE7中使用JSON

说明:
1,使用Delphi自己带的JSON(system.json)。

2,这仅仅是一个简单例子,以后还会增加演示功能。

注意:

1,JSON类创建后,里面所有元素不用管释放,JSON类自己管理,千万不要画蛇添足啊!!!!!!

作者:孙玉良 QQ:14667479 Email:sunylat@163.com 修改时间:2014/11/23 00:13

开发工具:Delphi XE7
测试手机:华为荣耀X1
}
unit Unit1;

interface

uses
System.SysUtils, System.Types, System.UITypes, System.Classes,
System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Layouts, FMX.Memo;

type
TForm1 = class(TForm)

Panel1: TPanel;
Memo1: TMemo;
Panel2: TPanel;
Button1: TButton;
Button2: TButton;
Memo2: TMemo;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormResize(Sender: TObject);

private

{ Private declarations }
// 重新设置button按钮
procedure ResetButton;

public

{ Public declarations }

end;

var
Form1: TForm1;

const
// 演示用的JSON
jsonString = '{"name":"张三", "other":["中国","程序员"]}';

implementation

{$R *.fmx}

uses
System.json; // Dephi自带的JSON单元

procedure TForm1.Button1Click(Sender: TObject);
var
JSONObject: TJSONObject; // JSON类
i: Integer; // 循环变量
temp: string; // 临时使用变量
jsonArray: TJSONArray; // JSON数组变量
begin

if Trim(Memo1.Text) = '' then
begin

ShowMessage('要解析数据不能为空!');

end
else
begin

JSONObject := nil;
try
  { 从字符串生成JSON }
  JSONObject := TJSONObject.ParseJSONValue(Trim(Memo1.Text)) as TJSONObject;
  if JSONObject.Count > 0 then
  begin
    { 1,遍历JSON数据 }
    Memo2.Lines.Add('遍历JSON数据:' + #13#10);
    Memo2.Lines.Add('JSON数据数量:' + IntToStr(JSONObject.Count));
    for i := 0 to JSONObject.Count - 1 do
    begin
      if i = 0 then
      begin
        temp := JSONObject.Get(i).ToString + #13#10;;
      end
      else
      begin
        temp := temp + JSONObject.Get(i).ToString + #13#10;
      end;
    end;
    { output the JSON to console as String }
    Memo2.Lines.Add(temp);
    Memo2.Lines.Add('------------------------------');
    { 2,按元素解析JSON数据 }
    Memo2.Lines.Add('按元素解析JSON数据:' + #13#10);
    temp := 'name = ' + JSONObject.Values['name'].ToString + #13#10;
    Memo2.Lines.Add(temp);
    // json数组
    jsonArray := TJSONArray(JSONObject.GetValue('other'));;
    if jsonArray.Count > 0 then
    begin
      // 得到JSON数组字符串
      temp := 'other = ' + JSONObject.GetValue('other').ToString + #13#10;
      // 循环取得JSON数组中每个元素
      for i := 0 to jsonArray.Size - 1 do
      begin
        temp := temp + IntToStr(i + 1) + ' : ' + jsonArray.Items[i]
          .Value + #13#10;
      end;
    end;
    Memo2.Lines.Add(temp);
  end
  else
  begin
    temp := '没有数据!';
    Memo2.Lines.Add(temp);
  end;
finally
  JSONObject.Free;
end;

end;

end;

// 清空显示数据
procedure TForm1.Button2Click(Sender: TObject);
begin
Memo1.Text := '';
Memo2.Text := '';
end;

// 设置要解析的JSON数据
procedure TForm1.Button3Click(Sender: TObject);
begin
Memo1.Text := jsonString;
end;

// 设置要解析的JSON数据
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Text := jsonString;
end;

procedure TForm1.FormResize(Sender: TObject);
begin
// 重新设置button按钮
self.ResetButton;
end;

// 重新设置button按钮
procedure TForm1.ResetButton;
var
buttonWidth: Integer;
begin
buttonWidth := self.Width div 3;

Button1.Width := buttonWidth;
Button2.Width := buttonWidth;
Button3.Width := buttonWidth;
end;

end.

18
Feb
0

SourceTree报ssh-agent失败 错误代码-1

20151211094435418.jpg

此时更新GIT版本到最新就解决这个问题了
注意64位还是32位版本

18
Feb
0

在 ASP.NET MVC 中使用 HTTPS (SSL/TLS)

某些安全性较高的网页,如网上支付或用户登陆页面,可能会使用到https(SSL/TLS)来提高安全性。本文介绍了如何在ASP.NET MVC中强制某action使用https和如何进行向https页面的跳转。
我们先实现强制一个action使用https。这里写了一个RequireHttpsAttribute,它的作用是将非https连接转换成https连接,这样所有使用了RequireHttps这个filter的controller都会强制使用https连接。

复制代码
1 using System.Web.Mvc;
2
3 namespace Snowdream.Demo.RequireHttps
4 {
5 public class RequireHttpsAttribute:AuthorizeAttribute
6 {
7 /// <summary>
8 /// 重写OnAuthorization方法
9 /// </summary>
10 /// <param name="filterContext"></param>
11 public override void OnAuthorization(AuthorizationContext filterContext)
12 {
13 // 如果已经是https连接则不处理,否则重定向到https连接
14 if (!filterContext.HttpContext.Request.IsSecureConnection)
15 {
16 // 获取当前请求的Path
17 string path = filterContext.HttpContext.Request.Path;
18
19 // 从web.config中获取host,也可以直接从httpContext中获取
20 string host = System.Configuration.ConfigurationManager.AppSettings["HostName"];
21
22 // 从web.config中获取https的端口
23 string port = System.Configuration.ConfigurationManager.AppSettings["HttpsPort"];
24
25 // 如果端口号为空表示使用默认端口,否则将host写成host:port的形式
26 if (port != null)
27 {
28 host = string.Format("{0}:{1}", host, port);
29 }
30
31 // 重定向到https连接
32 filterContext.HttpContext.Response.Redirect(string.Format("https://{0}{1}", host, path));
33 }
34 }
35 }
36 }
37
复制代码

由于https和https服务使用不同的端口号,而且https不能绑定主机头,只能通过不同端口的方式来区分各个站点,所以这里将host和port信息写到了web.config里,以方便配置。在web.config的appsettings节加入如下信息即可

1 <appSettings>
2 <add key="HostName" value="localhost"/>
3 <add key="httpsPort" value="443"/>
4 </appSettings>
5

HttpsPort可以不写,将使用默认的443。
然后在要使用https连接的controller或action前加上[RequireHttps],如

1 [RequireHttps]
2 public ActionResult About()
3 {
4 return View();
5 }
6

这样,当我们用http://localhost/Home/About访问该页面时会自动跳到https://localhost/Home/About。但是这样还有一个问题,网页中的链接都是http的,当点击进入需要使用https连接的网页时都要进行一次Redirect。所以我们要将网页中的链接也改成https。这步不难,只需要将view中所有链接到https页面的Html.Action()使用适当的重载方法来写即可。ASP.NET MVC 1.0 RTM中提供了2种重载可以将protocol设置为https。在新建ASP.NET MVC Web Application后默认生成的站点中,shared文件夹下有site.master文件中有个指向/Home/About的ActionLink。原来是

1 Html.ActionLink("Home", "Index", "Home")

我们对其进行改写

1 Html.ActionLink("About", "About", "Home", "https", "localhost", "",null, null)

这样,生成出来的链接就是https的了,点击以后直接会使用https连接而无需再进行一次Redirect,之后新的要到https页面的链接也可仿照次写法。
这里又要用到hostName信息,我们之前已经将它写在web.config里了,所以可以专门写一个方法来获取web.config中的这部分信息并拼接成这里需要的hostName字符串,或者还可以对HtmlHelper写一个扩展方法专门用于处理https的链接,这些可以在实际使用时做适当的优化。