导航:
论坛 ->
DELPHI技术 斑竹:liumazi,sephil
作者:
jjwwang (jjwwang)★☆☆☆☆-
普通会员
2023/8/9 16:54:14
标题:delphi自带的TJsonSerializer其实很好用了浏览:746
加入我的收藏楼主:unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
System.JSON.Serializers, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
type
TRecA = record
stringValue: string;
datetimeValue: TDateTime;
integerValue: Integer;
doubleValue: Double;
end;
TRecB = record
stringValue: string;
datetimeValue: TDateTime;
integerValue: Integer;
doubleValue: Double;
end;
TRecAB = record
A: TRecA;
B: TRecB;
end;
begin
var AB: TRecAB;
AB.A.stringValue := 'hello world';
AB.A.datetimeValue := Now;
AB.A.integerValue := 123;
AB.A.doubleValue := 3.1415926;
AB.B.stringValue := 'HELLO WORLD';
AB.B.datetimeValue := Now;
AB.B.integerValue := 666;
AB.B.doubleValue := 3.1415927;
var Arr: TArray<TRecAB>;
SetLength(Arr, 1);
Arr[0] := AB;
var s := TJsonSerializer.Create;
Memo1.Text := s.Serialize<TArray<TRecAB>>(Arr);
var d := TJsonSerializer.Create;
var EmptyArray: TArray<Integer> := d.Deserialize<TArray<Integer>>('[]');
Caption := Length(EmptyArray).ToString;
end;
end.
----------------------------------------------
学无止境
作者:
jjwwang (jjwwang)★☆☆☆☆-
普通会员
2023/8/9 16:55:34
1楼:记不清什么时候有的,个人感觉还是很好用的.
----------------------------------------------
学无止境
作者:
hnxxcxg (咏南中间件)★☆☆☆☆-
盒子活跃会员
2023/8/9 18:00:07
2楼:10.2 tokyo开始有的。
----------------------------------------------
中间件QQ群: 92449782 博客: http://www.cnblogs.com/hnxxcxg/
作者:
ksrsoft (cb168)★☆☆☆☆-
普通会员
2023/8/9 19:43:38
3楼:TJsonSerializer确实很好用 序列化 反序列化
----------------------------------------------
-
作者:
hi100 (hi100)▲▲▲▲△-
普通会员
2023/8/9 21:42:05
4楼:能不能把 Memo1.Text里的内容,再反序列化到数组呢?
----------------------------------------------
-
作者:
pcplayer (pcplayer)★☆☆☆☆-
普通会员
2023/8/9 21:43:22
4楼:能搞 TObjectList 吗?
----------------------------------------------
-
作者:
ghs_79 (ghs)★☆☆☆☆-
盒子活跃会员
2023/8/10 9:03:10
5楼:1、Memo1.Text当然可以么序列化。
var d := TJsonSerializer.Create;
var EmptyArray := d.Deserialize<TArray<TRecAB>>(Memo1.Text);
2、TObjectList<T>,泛型可以序列化。
----------------------------------------------
Delphi爱好者。
作者:
pcplayer (pcplayer)★☆☆☆☆-
普通会员
2023/8/10 12:59:05
6楼:泛型可以也行。我试试。
----------------------------------------------
-
作者:
pcplayer (pcplayer)★☆☆☆☆-
普通会员
2023/8/10 13:21:25
7楼:谢谢楼主。
我以前用的是 TJson.JsonToObject 和 TJson.ObjectToJsonString 感觉有 BUG;
这个 TJsonSerializer 针对 TObjectList 简单测试了一下,没有问题。
----------------------------------------------
-
作者:
jingzu (123456)★☆☆☆☆-
盒子活跃会员
2023/8/10 14:47:21
8楼:这个很好用啊,但怎么把 Memo1.Text 再放到AB(Arr[0])中?
----------------------------------------------
永远是DELPHI初学者。
作者:
ghs_79 (ghs)★☆☆☆☆-
盒子活跃会员
2023/8/10 17:17:25
9楼:用TObjectList<T>序列化格式的差异。
====objList直接序列化======
{"FOwnsObjects":true,"FListHelper":[{"Fid":1000,"FName":"测试中"}],"FComparer":{}}
====objList.ToArray()再序列化======
[{"Fid":1000,"FName":"测试中"}]
----------------------------------------------
Delphi爱好者。
作者:
hi100 (hi100)▲▲▲▲△-
普通会员
2023/8/10 17:35:43
10楼:感谢 ghs_79,测试可行。
----------------------------------------------
-
作者:
chencong5025 (Nicosoft)▲▲▲△△-
普通会员
2023/8/11 20:53:19
11楼:缺陷很明显 无法解析动态数据。
比如
type
MyRecord=record
name:string;
value:Tobject;
end;
Test=class
p1:string;
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
var json:='{"name":"你好","Value":{"p1":"value1"}}';
var ser:=TJsonSerializer.Create;
var outdata:=ser.Deserialize<Myrecord>(json);
memo1.Lines.Add(outdata.name);
if outdata.value=nil then
memo1.Lines.Add('null');
memo1.Lines.Add(Test(outdata.value).p1 );
end;
当然肯定有人会说 你要定义一个结构之类的。事实是 动态结构经常用,其他语言支持 Delphi不行
----------------------------------------------
-
作者:
powerpcer (大强)★☆☆☆☆-
普通会员
2023/8/11 21:05:10
12楼:动态结构经常用,其他语言支持, Delphi不行
Delphi是Native Language。
其他语言支持 的interpreter Language或Java/C#之類的 intermediate form Language。
不要拿跑車來拖貨。拖貨,請找回一般的貨車。大家目標不同。
致於說, 動不動態這一個東西嘛。
我都是用POINTER 來解決,NATIVE LANGUAGE 中,基本上不太需要哪種
給高級人用的高級貨。pointer 無敵。
對了你的"其他语言" 都是由Native Language 寫的而已哦。
----------------------------------------------
-
作者:
zhyhero (zhyhero)★☆☆☆☆-
盒子活跃会员
2023/8/12 9:10:42
13楼:为何不直接用value:TJsonobject
----------------------------------------------
z@S7
作者:
chencong5025 (Nicosoft)▲▲▲△△-
普通会员
2023/8/12 13:10:46
14楼:@powerpcer
最烦你这种人。不行就是不行 Delphi定位是RAD C#定位也是RAD 人家行 D不行 这有什么可叽歪的。
----------------------------------------------
-
作者:
powerpcer (大强)★☆☆☆☆-
普通会员
2023/8/12 14:47:42
15楼:@chencong5025
最烦你这种人。不懂就是不懂。出來叽歪什麼?
RAD 是指開發方法(或加上工具),快速應用程式開發(原名:Rapid Application Development、縮寫:RAD), 和語這無關。
Delphi 是語言,不是RAD。VCL FRAMEWORK 算RAD。
C# 是語言,不是RAD。.NET FRAMEWORK 算RAD。
.NET FRAMEWORK 上有C#, VB.NET, VJ 等.
VCL 上有DELPHI, C++ BUILDER 等.
不懂,真的不要先出言不遜!!
----------------------------------------------
-
作者:
ghs_79 (ghs)★☆☆☆☆-
盒子活跃会员
2023/8/12 16:14:03
16楼:类不行,可以用record来代替
Test = record
p1: string;
end;
MyRecord<T> = record
name: string;
value: T; //类不行,可以是记录
end;
----------------------------------------------
Delphi爱好者。
作者:
jjwwang (jjwwang)★☆☆☆☆-
普通会员
2023/8/13 11:58:43
17楼:type
MyRecord=record
name:string;
value:Tobject; //换为 Test应该能解决问题。
end;
Test=class
p1:string;
end;
如果还有
TestA = class
p1: string;
end;
TestB = class
p1: string;
end;
反序列化的时候,应该用哪个? 所以指定反序列化的需要指定具体类型。
----------------------------------------------
学无止境
作者:
janker (janker)★☆☆☆☆-
盒子活跃会员
2023/8/13 14:26:28
18楼:但是好像只对直接的“类型”进行操作,不对属性进行操作。
XI惯了只操作public和published的属性,这样好控制。
还有如何隐藏一些不要转换的字段,没搞明白。一些第三方的直接通过Attribute来控制隐藏成员和控制格式,指定大小写等。
----------------------------------------------
-
作者:
jjwwang (jjwwang)★☆☆☆☆-
普通会员
2023/8/13 16:04:53
19楼:to: 楼上
var s := TJsonSerializer.Create;
//TJsonDefaultContractResolver 默认是Fields,这里替换为public
s.ContractResolver := TJsonDefaultContractResolver.Create(TJsonMemberSerialization.&Public);
TJsonMemberSerialization = (Fields, &Public, &In);
另外,In不清楚什么意思,help文档里对这块没有描述,望清楚的大神给解下惑。
----------------------------------------------
学无止境
作者:
janker (janker)★☆☆☆☆-
盒子活跃会员
2023/8/13 17:33:09
20楼:@jjwwang 谢谢
用public,可以操作属性了,但是,好奇怪:
TMyChild = class
private
FAge: Integer;
FIsMoreCard: Boolean;
FTitle: string;
procedure SetTitle(const Value: string);
procedure SetAge(const Value: Integer);
procedure SetIsMoreCard(const Value: Boolean);
public
procedure Assign(Source: TObject);
property Title: string read FTitle write SetTitle;
property Age: Integer read FAge write SetAge;
property IsMoreCard: Boolean read FIsMoreCard write SetIsMoreCard;
end;
//{$M+}
TMyTestObj = class(TPersistent)
private
FNum: Integer;
FMSet: TMySet;
FStr: string;
FEnum: TMyEnum;
FStartDate: TDateTime;
FBirthDate: TDate;
FChild: TMyChild;
FStrList: TStrings;
FItems: TObjectList<TMyChild>;
FOthers: TObjectDictionary<string, TMyChild>;
procedure SetEnum(const Value: TMyEnum);
procedure SetMSet(const Value: TMySet);
procedure SetNum(const Value: Integer);
procedure SetStr(const Value: string);
procedure SetStartDate(const Value: TDateTime);
procedure SetBirthDate(const Value: TDate);
procedure SetChild(const Value: TMyChild);
procedure SetItems(const Value: TObjectList<TMyChild>);
procedure SetOthers(const Value: TObjectDictionary<string, TMyChild>);
procedure SetStrList(const Value: TStrings);
public
constructor Create;
destructor Destroy; override;
var TestStr: string;
property Items: TObjectList<TMyChild> read FItems write SetItems;
property StrList: TStrings read FStrList write SetStrList;
property Others: TObjectDictionary<string, TMyChild> read FOthers write SetOthers;
published
property Str: string read FStr write SetStr;
property Num: Integer read FNum write SetNum;
property Enum: TMyEnum read FEnum write SetEnum;
property StartDate: TDateTime read FStartDate write SetStartDate;
property BirthDate: TDate read FBirthDate write SetBirthDate;
property MSet: TMySet read FMSet write SetMSet;
property Child: TMyChild read FChild write SetChild;
end;
//{$M-}
测试:
aSer := TJsonSerializer.Create;
aSer.ContractResolver := TJsonDefaultContractResolver.Create(TJsonMemberSerialization.Public);
aSer.Formatting := TJsonFormatting.Indented; //格式化
结果:
========Serialize=======
{
"TestStr": "Test Test String",
"Items": {
"OwnsObjects": true,
"Capacity": 0,
"Count": 0,
"List": [],
"Comparer": {}
},
"StrList": {
"Duplicates": 0,
"Sorted": false,
"CaseSensitive": false,
"OwnsObjects": false,
"Updating": false,
"Capacity": 4,
"CommaText": "1234567890,222222222,333333333",
"Count": 3,
"DefaultEncoding": {
"CodePage": 936,
"EncodingName": "936 (ANSI/OEM - 简体中文 GBK)",
"MIMEName": "gbk",
"IsSingleByte": false
},
"Delimiter": ",",
"DelimitedText": "1234567890,222222222,333333333",
"Encoding": {
"CodePage": 936,
"EncodingName": "936 (ANSI/OEM - 简体中文 GBK)",
"MIMEName": "gbk",
"IsSingleByte": false
},
"LineBreak": "\r\n",
"QuoteChar": "\"",
"NameValueSeparator": "=",
"StrictDelimiter": false,
"Text": "1234567890\r\n222222222\r\n333333333\r\n",
"StringsAdapter": null,
"WriteBOM": true,
"TrailingLineBreak": true,
"UseLocale": true,
"Options": 14
},
"Others": {
"Capacity": 0,
"Count": 0,
"GrowThreshold": 0,
"Collisions": 0,
"Keys": {
"Count": 0
},
"Values": {
"Count": 0
},
"Comparer": {}
},
"Str": "中国人",
"Num": 123,
"Enum": 0,
"StartDate": "2023-08-13T17:31:27.566+08:00",
"BirthDate": "2003-01-30T00:00:00.000+08:00",
"MSet": 5,
"Child": {
"Title": "Child",
"Age": 22,
"IsMoreCard": true
}
}
对于TStringList,输出了不需要的。。。
----------------------------------------------
-
作者:
pcplayer (pcplayer)★☆☆☆☆-
普通会员
2023/8/13 17:41:32
21楼:哪些是不需要的?
----------------------------------------------
-
作者:
janker (janker)★☆☆☆☆-
盒子活跃会员
2023/8/13 17:55:04
22楼:@pcplayer
"Items": {
"OwnsObjects": true,
"Capacity": 0,
"Count": 0,
"List": [],
"Comparer": {}
},
"StrList": {
"Duplicates": 0,
"Sorted": false,
"CaseSensitive": false,
"OwnsObjects": false,
"Updating": false,
"Capacity": 4,
"CommaText": "1234567890,222222222,333333333",
"Count": 3,
"DefaultEncoding": {
"CodePage": 936,
"EncodingName": "936 (ANSI/OEM - 简体中文 GBK)",
"MIMEName": "gbk",
"IsSingleByte": false
},
"Delimiter": ",",
"DelimitedText": "1234567890,222222222,333333333",
"Encoding": {
"CodePage": 936,
"EncodingName": "936 (ANSI/OEM - 简体中文 GBK)",
"MIMEName": "gbk",
"IsSingleByte": false
},
这里的信息,好多是类本身的属性,不是用户数据。
Delphi内部用应当没问题,和其它语言交流就不行了
----------------------------------------------
-
作者:
pcplayer (pcplayer)★☆☆☆☆-
普通会员
2023/8/13 18:09:58
23楼:这些当然是有用的。没有这些信息,如果要把这个 JSON 恢复为一个 TStringList 对象,怎么恢复?
至于和其它语言交流,每个语言里面的对象都不一样,怎么交流?如果你仅仅需要用户数据,你直接用 StringList.Lines 就好了,它本身就是字符串。
没有格式这些信息,仅仅有用户数据,其它语言拿到,也没法使用。比如 "CodePage": 936, 这个如果没有,不管哪个语言,它也没法知道你的用户数据,也就是你的字符串,应该是什么编码,不知道编码,它怎么使用?
这个其实和【其它语言】无关。即便是 Delphi 这个语言,如果有另外一种 StringList 对象,它的代码实现方式和 TStringList 不一样,也没法使用这个 JSON 的。
说白了,JSON 本身是一种数据格式,但它并没有跨语言交换数据的标准,没有标准,当然就得自己处理。
就好比当年所有语言都狂推的 XML,它也是个数据格式。但是,基于 XML 数据格式的 SOAP 通讯协议,是有跨语言的标准的。所以如果两个语言都遵循 SOAP 协议,是可以互相调用的 -- 也就是一个语言输出的 XML 数据,另外一个语言能够使用。
但如果不是 SOAP 协议,而是自己用 XML 封装的数据,那其它语言,甚至相同语言的其它的代码,也不一定能解析理由这个数据。
----------------------------------------------
-
作者:
janker (janker)★☆☆☆☆-
盒子活跃会员
2023/8/13 18:12:51
23楼:用XSuperObject测试:TObjectList<T>可以,不会输出额外的信息。
用TJsonSerializer测试:TObjectList<T>还是会输出额外信息。
如果不想要额外信息,不要用TStringList, TDictionary, TObjectDictionary等容器。
----------------------------------------------
-
作者:
janker (janker)★☆☆☆☆-
盒子活跃会员
2023/8/13 18:16:44
24楼:@pcplayer
就是遇到了和Python,php,java等的交流情况,DELPHI做客户端,交流就是用json数据。
所以还得处理隐藏成员,改名,大小写等要求。
----------------------------------------------
-
作者:
powerpcer (大强)★☆☆☆☆-
普通会员
2023/8/13 18:43:09
25楼:@janker
如果有需要處理大小寫的問題,哪就表示定義JSON 的人是根本的菜鳥。
而json 格式,根本就是一個HASH,你自己PARSE 它再存到HASH中,就隨你想要了。
----------------------------------------------
-
作者:
pcplayer (pcplayer)★☆☆☆☆-
普通会员
2023/8/13 20:15:00
26楼:24 楼,这个和语言无关。和该语言的具体的库有关,甚至和使用该语言写某个具体的程序的人有关 -- 因为 JSON 只是数据的一种格式,但这个格式下的数据该是什么样子,并没有标准。所以,不可能随便一个格式的 JSON 数据,能够反序列化为某个具体类型的对象。比如,反序列化为 TStringList。反过来,假设 Python 里面有一个类叫做 TPyStringList,也不是随便一个 JSON 就能反序列化创建这个 TPyStringList 类型的对象的。
如果不处理具体的对象,仅仅是处理 JSON 格式封装的数据,那就用 Delphi 的 TJSONObject, TJSonPair 这样的单纯处理 JSON 数据的类。
所以,你的问题,要让 TStringList 输出的 JSON 去和其它程序(什么语言并不重要,即便那个程序是 Delphi 写的)沟通,本身就是个伪问题。本来就不应该这样做,也不可能这样做。这个和 Delphi 没关系。即便是一个 Python 写的程序,要和另外一个 Python 写的程序沟通,如果没有标准的通讯协议,两边处理 JSON 使用的类库不同,使用的类类型不同,也是没法直接把这边的对象输出的 JSON 到那边直接反序列化为另外一个对象的。都是肉,总不能这边的牛肉到那边变成猪肉吧?
----------------------------------------------
-
作者:
chencong5025 (Nicosoft)▲▲▲△△-
普通会员
2023/8/13 21:43:23
27楼:@powerpcer
你有意思么?抠字眼很好玩?是个人都知道我说的啥意思。
那Delphi也不算语言啊 Object-Pascal才算。真有意思。
----------------------------------------------
-
作者:
chencong5025 (Nicosoft)▲▲▲△△-
普通会员
2023/8/13 21:44:47
28楼:@jjwwang
如果制定了Test了的话 不就是固定了结构了
如果value 是个变化的 就不可以了。
C# 那边有个 动态类型了 现在可以包万物。包括序列化
----------------------------------------------
-
作者:
powerpcer (大强)★☆☆☆☆-
普通会员
2023/8/13 22:06:53
29楼:https://en.wikipedia.org/wiki/Delphi_(software)
Delphi is a general-purpose programming language and a software product that uses the Delphi dialect of the Object Pascal programming language and provides an integrated development environment (IDE) for rapid application development of desktop, mobile, web, and console software
在TIOBE Index,也明白說明,Delphi = Object Pascal.
你根本分不清RAD 和語言的關係,才會說哪種白話,還想硬扯回來。
更是搞不清楚native/intermediate/interpreted language 的差異。
才會講哪種笑話,用跑車來拉貨。都是車.....
----------------------------------------------
-
作者:
jjwwang (jjwwang)★☆☆☆☆-
普通会员
2023/8/13 22:18:54
30楼:TXXX = class
strValue: string;
arrObj: TArray<TMyObj>;
end;
对接其它语言过来的Json或提供json,上面方式基本上差不多了。在复杂的情况下,个人觉得要根据实际情况生成具体的json.
----------------------------------------------
学无止境
作者:
jjwwang (jjwwang)★☆☆☆☆-
普通会员
2023/8/13 22:19:53
31楼:
TObjectValue = class
private
FValue: string;
public
constructor Create(AValue: string);
property Value: string read FValue write FValue;
end;
TTestObject = class
private
FObjectList: TObjectList<TObjectValue>;
public
constructor Create;
destructor Destroy; override;
property ObjectList: TObjectList<TObjectValue> read FObjectList;
end;
{ TTestObject }
constructor TTestObject.Create;
begin
inherited Create;
FObjectList := TObjectList<TObjectValue>.Create;
FObjectList.Add(TObjectValue.Create('ABC'));
FObjectList.Add(TObjectValue.Create('A123'));
FObjectList.Add(TObjectValue.Create('B333'));
end;
destructor TTestObject.Destroy;
begin
FObjectList.Free;
inherited;
end;
{ TObjectValue }
constructor TObjectValue.Create(AValue: string);
begin
inherited Create;
FValue := AValue;
end;
像这种情况下,应该什么什么样的JSON呢?
----------------------------------------------
学无止境
作者:
jjwwang (jjwwang)★☆☆☆☆-
普通会员
2023/8/13 22:22:19
32楼:{
"ObjectList": {
"List": [
{
"Value": "ABC"
},
{
"Value": "A123"
},
{
"Value": "B333"
}
]
}
}
或
{
[
{
"Value": "ABC"
},
{
"Value": "A123"
},
{
"Value": "B333"
}
]
}
在不同的情况下,个人觉得这两种都是正确的.
----------------------------------------------
学无止境
作者:
janker (janker)★☆☆☆☆-
盒子活跃会员
2023/8/13 23:07:03
29楼:@pcplayer
我的意思不是凭空根据JSON就生成Delphi的Object,Delphi的Record。
一个具体的Delphi类型(Object,Record等)肯定一一对应一个JSON结构。
11楼说的那个动态类型,太厉害了,我想不通Delphi里怎么生成。
我是吐槽TJsonSerializer不方便使用,看了源码,也不知道怎么下手包装。
没有类似第三方的XSuperObject使用方便,不用包装就可以用于提交数据(比如微信,支付宝的API调用)。
比如使用XSuperObject:
1、TList<T>,TObjectList<T>,TArray<T>不会输出额外信息,这是希望的。TList<T>和TArray<T>都可以作为容器字段类型。
2、可以使用Alias这个Attribute可以方便改变字段名称,这个挺需要的。有些服务端提供的JSON结构,命名像天书,Delphi里还是XI惯简单明了的字段名称。
3、隐藏或忽略某些字段。这个也是挺需要的。比如ID字段,不希望JSON结构数据里传送这个ID,序列化的时候就可以通过Disabled或Ignore的Attribute来指明。
XSuperObject源码简单明了,XSuperObject添加一些定制的Attribute比较简单。
TJsonSerializer源码看得头晕,无从下手。
如果没有用到序列化部分,还可以用JsonDataObject这个JSON库。
只是JsonDataObject对序列化的支持太简单了,实际不够使用。有个开源的包装,开源项目DelphiMVCFrameWork,提供了JsonDataObject的序列化包装,但是感觉不如XSuperObject简单明了。
----------------------------------------------
-
作者:
jjwwang (jjwwang)★☆☆☆☆-
普通会员
2023/8/13 23:27:43
33楼:to: 楼上
[JsonIgnoreAttribute] //打上这个就不序列化了, delphi已内置定义了
property JsonIgnoreAttribute: string read FJsonIgnoreAttribute;
----------------------------------------------
学无止境
作者:
janker (janker)★☆☆☆☆-
盒子活跃会员
2023/8/13 23:35:42
34楼:@jjwwang
我看了半天,没找到JsonIgnoreAttribute在哪里声明
----------------------------------------------
-
作者:
janker (janker)★☆☆☆☆-
盒子活跃会员
2023/8/13 23:38:51
35楼:@jjwwang
找到了,在单元开头,呵呵...
----------------------------------------------
-
作者:
janker (janker)★☆☆☆☆-
盒子活跃会员
2023/8/14 0:04:11
36楼:再测试了下:
TJsonSerializer 用TArray<T>序列化后不会输出容器额外信息,
TList<T>和TObjectList<T>会额外输出容器信息
@jjwwang:是不是有地方可以关了这个额外输出的信息?
----------------------------------------------
-
作者:
pcplayer (pcplayer)★☆☆☆☆-
普通会员
2023/8/14 1:12:39
37楼:29 楼说的那些,其实是表明你不知道你的需求和 Delphi 的那个 TJsonSerializer 的设计目标,根本不是一回事。相当于你想吃猪肉,去吐槽一家牛肉店。
TJsonSerializer 能够解决我想要的一个需求:把一堆的对象,也就是 TObjectList 里面的一堆对象,序列化为字符串,然后再反序列化为 TObjectList;它要解决这个,不带任何的类信息或者对象信息,很难搞。
你要的是仅仅输出数据。但是,仅仅输出数据,其实并不是你要的。你还没明白你要什么。需求分析,正确地提出自己的需求和问题,才是问题的核心。
对于 JSON 来说,它就是用字符串来表达的一种数据格式,类似 XML。在遵循它的基本格式的情况下,同样的数据,不同的人,设计的具体格式可能不同。这也就是我说的,你输出的 JSON 格式,不一定能给另外一个程序用,不管这个程序是什么语言写的。除非大家对于格式有个约定,有一个相同的格式标准。
所以,问题并不是什么只要数据,不要类的信息之类的问题。前面我也说了,输出的字符串列表,如果输出信息里面不包含编码信息,另外一边拿到这个 JSON 也无法处理。但是,包含编码信息的话,JSON 又没有一个标准说这个编码信息必须放在哪里,因为没有标准,如果另外一个接收信息的程序它处理数据的标准不一样,也没法处理。
同样是字符串,比如 HTML 就有标准,必须在头部有 <meta CharSet="UTF8"/> 这样的信息。既然它是标准,那么不管什么语言,处理 HTML 的代码,就都会处理。如果没有这个标准,一个语言处理这个信息时认为它应该在头部(<head>),另外一个语言处理这个信息时认为它应该在 <Body> 部分,那么 A 程序输出的 HTML 给到 B 程序也没法正确处理。
因此,你要的不是仅仅输出数据,而是输出的数据的 JSON 格式,符合你目前面对的需求环境,比如,假设你目前需要对接某个其它的系统,不管这个系统是用什么语言开发的,你需要搞明白的是那个系统需要的数据结构,JSON 的格式。
所以,这里没什么好吐槽的。Delphi 能够做的其实就 2 种:
A. Delphi 自己的类输出的 JSON 数据再转化为 Delphi 自己的类。这种情况,Delphi 自己搞定,无需考虑别人有什么格式或者标准。这个就是 TStringList 的情况;
B. 如果有业界标准,Delphi 如果决定支持这个业界标准,那它会有库,输出符合业界标准的 JSON;
至于你现在想要的那种数据格式,如果没有业界标准,那肯定 Delphi 官方的代码不会去支持,你想要就只能自己写代码实现了。
----------------------------------------------
-
作者:
jjwwang (jjwwang)★☆☆☆☆-
普通会员
2023/8/14 8:58:16
38楼:to: 是不是有地方可以关了这个额外输出的信息?
我没找到取巧的办法,都是用TArray<T>
----------------------------------------------
学无止境
作者:
jjwwang (jjwwang)★☆☆☆☆-
普通会员
2023/8/14 9:03:47
39楼: TTestObject = class
private
FObjectList: TObjectList<TObjectValue>;
function GetObjectArray: TArray<TObjectValue>;
public
constructor Create;
destructor Destroy; override;
[JsonIgnoreAttribute]
property ObjectList: TObjectList<TObjectValue> read FObjectList;
property ObjectArray: TArray<TObjectValue> read GetObjectArray;
end;
{
"ObjectArray": [
{
"Value": "ABC"
},
{
"Value": "A123"
},
{
"Value": "B333"
}
]
}
这是目前我能想到的
----------------------------------------------
学无止境
作者:
janker (janker)★☆☆☆☆-
盒子活跃会员
2023/8/14 13:02:00
40楼:@jjwwang
固定用TArray<T>也行,只是没有TList<T>方便。
内置的Attribute:
JsonConverterAttribute:这个是干嘛的,难道是就是干11楼说的动态解析用的?
JsonIgnoreAttribute:隐藏
JsonNameAttribute:改名
JsonInAttribute:这个不知道干嘛
JsonObjectHandlingAttribute:这个也不知道干嘛
JsonObjectOwnership:这个是拥有关系
JsonSerializeAttribute:这个是指定序列化器?
没有文档,没有Demo....
----------------------------------------------
-
作者:
chencong5025 (Nicosoft)▲▲▲△△-
普通会员
2023/8/14 13:31:19
41楼:@powerpcer
有个成语叫固步自封 可以研究下。
就你还在着 跑车货车 人家C#是什么车 你来说说
----------------------------------------------
-
作者:
jjwwang (jjwwang)★☆☆☆☆-
普通会员
2023/8/14 14:46:07
42楼:完善版贴子在这里
https://bbs.2ccc.com/topic.asp?topicid=681707
----------------------------------------------
学无止境
作者:
powerpcer (大强)★☆☆☆☆-
普通会员
2023/8/14 14:56:41
43楼:@chencong5025,
你最好還是連中文也回去重讀吧。
因為你真的連基本的中文看不懂。
等你看懂中文, 再來討論吧。
將RAD 當LANGUAGE,當NATIVE 拿來和INTERMEDIA 比。
寫程式,真的是人人都可以會。
但要理解程式的本質,就需要下功夫。
----------------------------------------------
-
作者:
isxuzhu (e.Wong)★☆☆☆☆-
盒子活跃会员
2023/8/14 16:58:27
44楼:收藏,学xi了
----------------------------------------------
你我,都可以是个造梦者!欢迎加入脚本引擎PaxCompiler交流群303904495http://www.cnblogs.com/fireboxsoft有需要错别字检测软件的朋友可以在我博客上的地址下载使用,备注“2ccc”的朋友可以免费获取超级黄金VVVVVVVVVVIP授权
回复此贴
UBB标签:
贴子内容:
滑动验证:>> 请按住滑块,拖动到最右边
邮件通知:如果有回复请邮件通知我
包含附件:
大小限制:19.90M,扩展名限制:gif|jpg|png|doc|zip|rar|chm|pdf|mid|mp3|asf|rm|swf|txt
(Ctrl+Enter提交)