Delphi / Lazarus / C ++ Builder Kelas Sederhana dan Kecil untuk Parsing JSON FAST.
Beberapa tempat menarik:
McJSON ), hanya satu kelas ( TMcJsonItem ). uses
McJSON;
...
function Test99 (out Msg: string): Boolean;
var
Json: TMcJsonItem;
i: Integer;
begin
Msg := ' Test: Github readme.md content ' ;
Json := TMcJsonItem.Create();
try
try
// add some pairs.
Json.Add( ' key1 ' ).AsInteger := 1 ;
Json.Add( ' key2 ' ).AsBoolean := True;
Json.Add( ' key3 ' ).AsNumber := 1.234 ;
Json.Add( ' key4 ' ).AsString := ' value 1 ' ;
// add an array
Json.Add( ' array ' , jitArray);
for i := 1 to 3 do
Json[ ' array ' ].Add.AsInteger := i;
// save a backup to file
if (Json[ ' array ' ].Count = 3 ) then
Json.SaveToFile( ' test99.json ' );
// remove an item
Json.Delete( ' array ' );
// oops, load the backup
if (Json.Count = 4 ) then
Json.LoadFromFile( ' test99.json ' );
// test final result
Result := (Json.AsJSON = ' {"key1":1,"key2":true,"key3":1.234,"key4":"value 1","array":[1,2,3]} ' );
except
Result := False;
end ;
finally
Json.Free;
end ;
end ; Akan menghasilkan testtest99.json :
{
"key1" : 1 ,
"key2" : true ,
"key3" : 1.234 ,
"key4" : " value 1 " ,
"array" : [
1 ,
2 ,
3
]
}# include " McJson.hpp "
...
bool Test99 (AnsiString& Msg)
{
bool Result;
TMcJsonItem* Json = NULL ;
Msg = " Test: Github readme.md content " ;
Json = new TMcJsonItem ();
try
{
try
{ // add some pairs.
Json-> Add ( " key1 " )-> AsInteger = 1 ;
Json-> Add ( " key2 " )-> AsBoolean = true ;
Json-> Add ( " key3 " )-> AsNumber = 1.234 ;
Json-> Add ( " key4 " )-> AsString = " value 1 " ;
// add an array
Json-> Add ( " array " , jitArray);
for ( int i = 1 ; i <= 3 ; i++)
Json-> Values [ " array " ]-> Add ()-> AsInteger = i;
// save a backup to file
if (Json-> Values [ " array " ]-> Count == 3 )
Json-> SaveToFile ( " test99.json " );
// remove an item
Json-> Delete ( " array " );
// oops, load the backup
if (Json-> Count == 4 )
Json-> LoadFromFile ( " test99.json " );
// test final result
Result = (Json-> AsJSON ==
" { " key1 " :1, " key2 " :true, " key3 " :1.234, " key4 " : " value 1 " , " array " :[1,2,3]} " );
}
catch (...)
{
Result = false ;
}
}
__finally
{
if (Json) delete (Json);
}
return (Result);
} Harap mempertimbangkan tes unit baca di folder test untuk daftar lengkap kasus penggunaan McJSON .
Gunakan saja properti AsJSON
var
N: TMcJsonItem;
begin
N := TMcJsonItem.Create;
N.AsJSON := ' {"i": 123, "f": 123.456, "s": "abc", "b": true, "n": null} ' ;
// use N here
N.Free;
end ; Jika Anda ingin memeriksa apakah string JSON valid:
Answer := N.Check( ' {"i":[123} ' ); // Answer will be false Metode Check tidak akan menaikkan pengecualian. Contoh di atas akan menangkap dan menyembunyikan Error while parsing text: "expected , got }" at pos "10" pengecualian. Jika Anda perlu menangkap dan mengelola pengecualian, gunakan CheckException seperti:
try
Answer := N.CheckException( ' {"k":1, "k":2} ' ); // Answer will be false
except
on E: Exception do
begin
// Error while parsing text: "duplicated key k" at pos "11"
end ;
end ; McJSON memungkinkan cara sederhana untuk mengakses item melalui jalur. Kita dapat menggunakan '/', '' atau '.' sebagai pemisah jalur.
N.AsJSON := ' {"o": {"k1":"v1", "k2":"v2"}} ' ;
// access and change second object's value
N.Path( ' o.k2 ' ).AsString := ' value2 ' ;Hasil dalam:
{
"o" : {
"k1" : " v1 " ,
"k2" : " value2 "
}
} Perhatikan bahwa Path() belum menerima indeks, seperti ini:
N.AsJSON := ' {"o": [{"k1":"v1"}, {"k2":"v2"}] ' ;
N.Path( ' o[1].k2 ' ).AsString := ' value2 ' ; Karena versi 1.0.4 McJSON memungkinkan untuk menggunakan pemendekan properti seperti di objek data JSON Andreas Hausladen.
// access (automatic creation as in JDO)
Obj.S[ ' foo ' ] := ' bar ' ;
Obj.S[ ' bar ' ] := ' foo ' ;
// array creation, Obj is the owner of 'array'
Obj.A[ ' array ' ].Add.AsInteger := 10 ;
Obj.A[ ' array ' ].Add.AsInteger := 20 ;
// object creation, 'array' is the owner of ChildObj
ChildObj := Obj[ ' array ' ].Add(jitObject);
ChildObj.D[ ' value ' ] := 12.3 ;
// array creation, ChildObj is the owner of 'subarray'
ChildObj.A[ ' subarray ' ].Add.AsInteger := 100 ;
ChildObj.A[ ' subarray ' ].Add.AsInteger := 200 ;Hasil dalam:
{
"foo" : " bar " ,
"bar" : " foo " ,
"array" :[
10 ,
20 ,
{
"value" : 12.3 ,
"subarray" :[
100 ,
200
]
}
]
}Berikut adalah cara mengakses semua item (anak -anak) dari objek JSON dan mengubah jenis nilai dan kontennya.
N.AsJSON := ' {"o": {"k1":"v1", "k2":"v2"}} ' ;
// type and value: from string to integer
for i := 0 to N[ ' o ' ].Count- 1 do
N[ ' o ' ].Items[i].AsInteger := i+ 1 ; Hasil dalam:
{
"o" : {
"k1" : 1 ,
"k2" : 2
}
} Kita dapat menggunakan Items[index] dan Values['key'] properti untuk mengakses item di dalam objek dan array. Karena versi 0.9.5 , kita dapat menggunakan At(index, 'key') atau At('key', index) sebagai pemendek.
N.AsJSON := ' {"a": [{"k1":1,"k2":2},{"k1":10,"k2":20}]} ' ;
// how to access k2 of second object.
i := N[ ' a ' ].Items[ 1 ].Values[ ' k2 ' ].AsInteger; // i will be equal to 20
i := N[ ' a ' ].Items[ 1 ][ ' k2 ' ].AsInteger; // uses the Values[] as default property
i := N[ ' a ' ].At( 1 , ' k2 ' ).AsInteger; // shortener: index, key
i := N.At( ' a ' , 1 )[ ' k2 ' ].AsInteger; // shortener: key, index Dan ada kegunaan lain tanpa parameter key :
N.AsJSON := ' {"k1":1,"k2":2,"k3":3,"k4":4} ' ;
i := N.Items[ 2 ].AsInteger; // i will be equal to 3
i := N.At( 2 ).AsInteger; // shortener: just index
i := N.At( ' k3 ' ).AsInteger; // shortener: just keyMenggunakan Enumerator Delphi Anda dapat menelusuri anak -anak dan nilai objek item.
var
N, item: TMcJsonItem;
begin
N := TMcJsonItem.Create;
N.AsJSON := ' {"o": {"k1":"v1", "k2":"v2"}} ' ;
for item in N[ ' o ' ] do
// use item here, e.g. item.Key, item.Value, item.AsStringUbah semua nilai objek dengan beberapa item. Tidak begitu umum di luar sana.
N.AsJSON := ' {"o": {"k1":"v1", "k2":"v2"}} ' ;
N[ ' o ' ].AsString := ' str ' ;Hasil dalam:
{
"o" : {
"k1" : " str " ,
"k2" : " str "
}
} Dan jika perlu mengubah jenis o :
N[ ' o ' ].ItemType := jitValue;
N[ ' o ' ].AsString := ' str ' ;Hasil dalam:
{
"o" : " str "
}Konversi dari array ke jenis objek dan sebaliknya. Juga, tidak terlalu umum di luar sana.
N.AsJSON := ' { "k1": ["1", "2"], "k2": {"1": "a", "2": "b"} } ' ;
N[ ' k1 ' ].ItemType := jitObject; // convert array to object with items
N[ ' k2 ' ].ItemType := jitArray ; // convert object with items to array Hasil dalam:
{
"k1" : {
"0" : " 1 " ,
"1" : " 2 "
},
"k2" : [
" a " ,
" b "
]
}Masukkan beberapa item menggunakan kunci dan posisi.
P.Insert( ' c ' , 0 ).AsInteger := 3 ;
P.Insert( ' b ' , 0 ).AsInteger := 2 ;
P.Insert( ' a ' , 0 ).AsInteger := 1 ;Hasil dalam:
{
"a" : 1 ,
"b" : 2 ,
"c" : 3
}Juga, dimungkinkan untuk memasukkan objek dalam array.
Q.AsJSON := ' {"x":0} ' ;
P.ItemType := jitArray;
P.Insert(Q, 1 );Hasil dalam:
[
1 ,
{
"x" : 0
},
2 ,
3
] PENTING : Karena versi 0.9.3, Add() dan Insert() akan mengkloning argumen tipe TMcJsonItem . Jadi, kita harus membebaskan memori untuk Q juga:
P.Free;
Q.Free; Karena versi 1.0.5 string dapat diloloskan dengan fungsi helper McJsonEscapeString() :
N.AsJSON := ' {"path": ' + McJsonEscapeString( ' dirsubdir ' ) + ' } ' ; Hasil dalam:
{
"path" : " \ dir \ subdir "
} Dalam versi 1.0.6 diperkenalkan TJEscapeType enum yang digunakan dalam McJsonEscapeString() dengan level pelarian ini:
jetNormal : Escapes #8 #9 #10 #12 #13 " .jetStrict : Normal + / .jetUnicode : ketat + uXXXX .jetNone : Kompatibilitas ke belakang. Level -level ini diilhami oleh fungsi pembantu Lazarus StringToJSONString() dari perpustakaan fpjson.
Mari kita lihat cara memeriksa semua struktur data, jenis, dan nilai -nilai dari objek TMcJsonItem .
// ---------------------------------------------------------------------------
void
TFormMain::Inspect (TMcJsonItem* AMcJItem, AnsiString Ident)
{
if (!AMcJItem) return ;
// log current
MyLog ( Ident + ItemToStr (AMcJItem) );
// log child
if ( AMcJItem-> HasChild )
{
Ident = " " + Ident;
for ( int i= 0 ; i < AMcJItem-> Count ; i++)
{ // use Value not Child because are note using Key[].
Inspect ( AMcJItem-> Items [i], Ident );
}
}
}
// ---------------------------------------------------------------------------
String
TFormMain::ItemToStr (TMcJsonItem* AMcJItem) const
{
String Ans = " " ;
if (AMcJItem)
Ans = AMcJItem-> GetTypeStr () +
" ; " + AMcJItem-> GetValueStr () +
" ; Key= " + AMcJItem-> Key +
" ; Value= " + AMcJItem-> Value +
" ; JSON= " + AMcJItem-> AsJSON ;
return (Ans);
}
// --------------------------------------------------------------------------- Dan menggunakan contoh seperti testInspect.json :
{
"foo" : " bar " ,
"array" : [
100 ,
20
],
"arrayObj" : [
{
"key1" : 1.0
},
{
"key2" : 2.0
}
],
"Msg" : [
" #1 UTF8 example: motivação " ,
" #2 Scapes: btnfr\ uFFFF "\ "
]
} Calling Inspect() dengan objek Json yang dimuat dengan testInspect.json :
TMcJsonItem* Json = new TMcJsonItem();
if (Json)
{
Json-> LoadFromFile ( " testInspect.json " );
Inspect (Json);
delete (Json);
}Hasil dalam:
object; string; Key=; Value=; JSON={"foo":"bar","array":[100,20],"arrayObj":[{"key1":1.0},{"key2":2.0}],"Msg":["#1 UTF8 example: motivação","#2 Scapes: btnfru"\"]}
value; string; Key=foo; Value=bar; JSON="foo":"bar"
array; string; Key=array; Value=; JSON="array":[100,20]
value; number; Key=; Value=100; JSON=100
value; number; Key=; Value=20; JSON=20
array; string; Key=arrayObj; Value=; JSON="arrayObj":[{"key1":1.0},{"key2":2.0}]
object; string; Key=; Value=; JSON={"key1":1.0}
value; number; Key=key1; Value=1.0; JSON="key1":1.0
object; string; Key=; Value=; JSON={"key2":2.0}
value; number; Key=key2; Value=2.0; JSON="key2":2.0
array; string; Key=Msg; Value=; JSON="Msg":["#1 UTF8 example: motivação","#2 Scapes: btnfruFFFF"\"]
value; string; Key=; Value=#1 UTF8 example: motivação; JSON="#1 UTF8 example: motivação"
value; string; Key=; Value=#2 Scapes: btnfruFFFF"\; JSON="#2 Scapes: btnfruFFFF"\"
Sejak versi 0.9.0 , tombol kosong akan diuraikan dan diperiksa dengan kesalahan Anda:
N.AsJSON := ' {"": "value"} ' ; Dan ToString() akan menghasilkan objek JSON yang valid:
{
"" : " value "
}Secara internal, itu akan menggunakan string konstan c_empty_key sebagai konten dari bidang FKEY.
Karena versi 0.9.2 , string dengan jeda garis yang tidak melarikan diri akan diuraikan dengan kesalahan:
N.AsJSON := ' {"key": "value ' + # 13 + ' "} ' ;Akan meningkatkan pengecualian:
Error while parsing text: "line break" at pos "14"
McJSON dapat memuat dari file ASCII dan UTF-8 (dengan atau tanpa BOM). Lihat metode LoadFromFile . Metode SaveToFile akan menulis menggunakan pengkodean UTF-8. Catatan : Karena Vertion 1.0.4, kode sumber proyek uji di Lazarus dikonversi ke UTF-8, sehingga parameter asUTF8 diatur ke false .
Dunia tidak sempurna dan saya juga tidak. Berikut beberapa masalah yang diketahui:
TMcJsonItem dipakai dalam struktur hierarkis menggunakan daftar fChild , ada masalah untuk membuat bidang yang merambat secara otomatis di antara item. Solusi yang diteliti mencoba membuat kelas induk baru TMcJson yang objek akan seperti akar dan memiliki objek TMcJsonItem sebagai anak -anaknya. Tes kinerja telah dilakukan dengan unit myJSON , LkJson , JsonTools dan uJSON asli. Berikut adalah ringkasan tes.
{... {"keyi":"valuei"}... }Dan tentang kompiler dan mesin yang digunakan:
Tabel berikutnya merangkum hasil 1 :
| Perpustakaan | Menghasilkan | Menyimpan | Parse | Memuat | Mengakses | Total |
|---|---|---|---|---|---|---|
McJSON 2 | .11 s | .07 s | .12 s | .09 s | .83 s | 1.25 s |
LkJson 2 | .30 s | .11 s | .47 s | .36 s | .01 s | 1.24 s |
JsonTools | 48.00 s | .70 s | 39.00 s | 40.00 s | .48 s | 1,2 menit |
myJSON | 50,00 s | .07 s | 5,1 menit | 7,7 menit | 1.60 s | 13.1 mnt |
uJSON | 18,6 menit | 20.1 menit | 17,5 menit | 4.31 s | 53.02 s | 57,6 menit |
McJSONJson->Add("key")->AsString = "value" .JsonP->AsJSON = Json->AsJSON .LkJsonTlkBalTree .dynamic_cast membuat kode verbosy.Json->Add("key", "value") .JsonP = dynamic_cast<TlkJSONObject*>(TlkJSON::ParseText(NULL, TlkJSON::GenerateText(NULL, Json))) .JsonToolsJson->Add("key", "value") .JsonP->Value = Json->AsJson .myJSONJson->Item["key"]->setStr("value") .JsonP->Code = Json->getJSON() .uJSONLkJson , tetapi koleksi kelas juga akan memaksa casting dengan dynamic_cast .uJSON , tampaknya ada masalah kinerja yang terkait dengan toString() .Json->put("key", "value") .JsonP = new TJSONObject(Json->toString()) .SaveToFile tidak ada, jadi telah menggunakan TStringList->SaveToFile() setelah mengisi Text dengan Json->toString() . Metrik: Waktu rata -rata dalam detik untuk 5 eksekusi berturut -turut. Total adalah rata -rata tes parsial. Beberapa hasil dikonversi menjadi menit (min). ↩
Versi 1.0.5. Proyek Tes JSON 0.9.0 yang ditingkatkan yang akan segera dirilis. ↩ ↩ 2