import std.stdio;
import std.json;
import std.traits;
import std.exception;
import std.string;
import std.conv;
/*
* Verilen değeri JSONValue'ya dönüştürür.
*/
JSONValue to(Hedef : JSONValue, T)(T değer)
{
JSONValue json;
static if (isSomeString!T) {
json.type = JSON_TYPE.STRING;
json.str = std.conv.to!string(değer);
} else static if (__traits(compiles, *değer)) {
if (!değer) {
json.type = JSON_TYPE.NULL;
} else {
/* Göstergeleri nasıl JSONValue olarak ifade edeceğimizi
* bilmiyoruz. */
assert(false);
}
} else static if (is (T : bool)) {
json.type = değer ? JSON_TYPE.TRUE : JSON_TYPE.FALSE;
} else static if (is (T : long)) {
static if (is (T == ulong)) {
/* std.json long türünü kullandığı için ulong'un bazı değerlerini
* tutamaz. Güvenlik amacıyla bu durumu denetlemek için ulong için
* ayrı bir 'static if' koşulu yazıyoruz. */
enforce(değer <= long.max,
format("Veri kaybı: Bir %s değeri olan %s, long'a sığamaz!",
T.stringof, değer));
}
json.type = JSON_TYPE.INTEGER;
json.integer = değer;
} else static if (is (T : real)) {
json.type = JSON_TYPE.FLOAT;
json.floating = değer;
} else static if (isArray!T) {
json.type = JSON_TYPE.ARRAY;
foreach (eleman; değer) {
json.array ~= to!JSONValue(eleman);
}
} else static if (isAssociativeArray!T) {
json.type = JSON_TYPE.OBJECT;
JSONValue[string] elemanlar;
foreach (anahtar, eleman; değer) {
elemanlar[std.conv.to!string(anahtar)] = to!JSONValue(eleman);
}
json.object = elemanlar;
} else static if (__traits(compiles, cast(JSONValue)değer)) {
json = cast(JSONValue)(değer);
} else {
static assert(false,
"Bu tür JSONValue'ya dönüştürülemez: " ~ T.stringof);
}
return json;
}
unittest
{
import std.typetuple;
/* ulong'un değer aralığının üst yarısı long'a sığmaz. Onun için ayrıca
* deniyoruz. */
to!JSONValue(cast(ulong)0);
to!JSONValue(cast(ulong)long.max);
/* Güvenlik gerçekten işe yarıyor mu? */
bool hataAtıldı_mı = false;
try {
to!JSONValue(ulong.max);
} catch (Exception) {
hataAtıldı_mı = true;
}
assert(hataAtıldı_mı, "ulong.max için hata atılmadı!");
/* Her temel tür kullanılabilmeli. */
alias TypeTuple!(byte, ubyte, short, ushort, int, uint, long, /* ulong, */
bool,
int*,
float, double, real,
string, wstring, dstring, char[], wchar[], dchar[],
int[], string[double])
Türler;
foreach (Tür; Türler) {
to!JSONValue(Tür.init);
}
}
/*
* mixin() olarak kullanılabilecek bir işlev: Belirtilen JSONValue eşleme
* tablosuna belirtilen isimdeki değişkenin JSONValue karşılığını ekleyen
* ifadeyi dizgi olarak döndürür.
*/
@property string eklemeİfadesi(string tabloİsmi,
string değişkenİsmi)()
{
enum solTaraf = tabloİsmi ~ `["` ~ değişkenİsmi ~ `"]`;
enum sağTaraf = `to!JSONValue(` ~ değişkenİsmi ~ `);`;
return solTaraf ~ "=" ~ sağTaraf;
}
unittest
{
assert(eklemeİfadesi!("üyeler", "foo")
== `üyeler["foo"]=to!JSONValue(foo);`);
}
/*
* mixin() olarak kullanılabilecek bir işlev: Belirtilen türün bütün
* üyelerinin JSONValue karşılıklarını belirtilen tabloya ekleyen ifadeleri
* dizgi olarak döndürür.
*/
@property string eklemeİfadeleri(T, string tabloİsmi)()
{
enum size_t fazlalık = 3; /* Parantezler ve nokta */
enum size_t kırpılacaklar = T.stringof.length + fazlalık;
string eklemeİfadeleri;
foreach (i, üyeTürü; typeof(T.tupleof)) {
enum değişkenİsmi = T.tupleof[i].stringof[kırpılacaklar..$];
eklemeİfadeleri ~= eklemeİfadesi!(tabloİsmi, değişkenİsmi);
}
return eklemeİfadeleri;
}
unittest
{
struct BirYapı
{
int foo;
double bar;
}
assert(`üyeler["foo"]=to!JSONValue(foo);üyeler["bar"]=to!JSONValue(bar);`
== eklemeİfadeleri!(BirYapı, "üyeler"));
}
/*
* mixin() olarak kullanılabilecek bir işlev: Belirtilen türün bütün üyelerini
* teker teker JSONValue'lara dönüştüren ve nesneyi tek bir JSONValue olarak
* döndüren bir opCast() işlecinin tanımını dizgi olarak döndürür.
*/
@property string BütünÜyelerİçin_opCastJSONValue(T)()
{
enum işlevBaşı = `
JSONValue opCast(T : JSONValue)() const @property
{
JSONValue json;
JSONValue[string] üyeler;
`;
enum eklemeİfadeleri = eklemeİfadeleri!(T, "üyeler");
enum işlevSonu = `
json.type = JSON_TYPE.OBJECT;
json.object = üyeler;
return json;
}
`;
return işlevBaşı ~ eklemeİfadeleri ~ işlevSonu;
}
unittest
{
struct BirYapı
{
int foo;
double bar;
mixin(BütünÜyelerİçin_opCastJSONValue!BirYapı);
}
/* Derlenebilmesi yeterli. */
auto nesne = BirYapı();
auto json = cast(JSONValue)nesne;
}
struct İçYapı
{
int i = 42;
double d = 6.75;
mixin(BütünÜyelerİçin_opCastJSONValue!İçYapı);
}
struct Öğrenci
{
string isim;
ulong numara;
uint[string] notlar; /* ders ismi : not */
bool boolDenemesi;
İçYapı içYapım;
float * f;
mixin(BütünÜyelerİçin_opCastJSONValue!Öğrenci);
}
JSONValue JSONBelgesi()
{
JSONValue json;
json.type = JSON_TYPE.OBJECT;
return json;
}
void main()
{
auto öğrenciler = [ Öğrenci("Ayşe", 12,
[ "matematik" : 90, "ingilizce" : 100 ]),
Öğrenci("Başak", 34,
[ "matematik" : 95, "ingilizce" : 99 ]) ];
JSONValue belge = JSONBelgesi();
belge.object["öğrenciler"] = to!JSONValue(öğrenciler);
writeln(toJSON(&belge));
}