天天看點

03序化枚舉和類

​​原位址​​

​序化枚舉​

​,先要考慮是序化​

​值/名字​

​.我們按​

​名​

​序化,

enum PersonType
{
Unknown,
Student,
Staff
}

struct Person
{
string name;
int age;
PersonType type;
}
      

按​

​值類型​

​檢查,則是

is(PersonType==int)
//或
isNumeric!PersonType
      

​名​

​則是,

is(T == enum)
      

​原始類型​

​中,我們可忽略​

​枚舉​

enum isPrimitiveType(T) = !is(T == enum) && (isNumeric!T || is(T == bool) || is(T == string));
//第1個判斷式.
JSONValue serialise(T)(T value)
{    
static if(isPrimitiveType!T)
    { /* ... */ }
else static if(is(T == enum))
    {
return JSONValue(value.to!string());
// PersonType.Student -> "Student", PersonType.Staff -> "Staff", etc.
    }//值轉串.
    ...
}
      

反序化:

T deserialise(T)(JSONValue json)
{
static if(is(T == enum))
    {//放第1個
// "Student"->PersonType.Student,etc.
return json.str.to!T();
    }
    ...
}
      

測試:

void main()
{
import std.stdio : writeln;

auto json = serialise(PersonType.Student);
writeln(json);
writeln(json.deserialise!PersonType());

json = serialise(Person("Bradley", 20, PersonType.Student));
writeln(json);
writeln(json.deserialise!Person());

/*
輸出:
"Student"
Student
{"age":20,"name":"Bradley","type":"Student"}
Person("Bradley", 20, Student)
*/
}
      

​類​

​與​

​構​

​不一樣:

​序号​

與​

​構​

​不同的特點

​1​

類可為​

​無效​

​.

​2​

不能可靠建構​

​類​

​3​

不能直接暴露​

​類​

​變量,等等

​類/構​

​一起:

else static if(is(T == struct) || is(T == class)) //記得檢查類.
{
JSONValue toReturn;

static if(is(T == class))
    {
if(value is null)
        {
return JSONValue(null);
        }//處理空類.
    }
else
    {
T toReturn; // 類預設為`無效`,我們不能重用這句
    }

static foreach(member; T.tupleof)
    {{
/**/
    }}

return toReturn;
}
      

簡單測試:

void main()
{
import std.stdio : writeln, writefln;
auto p = new Person();
p.name = "Bradley";
p.age = 20;
p.type = PersonType.Student;

auto json = p.serialise();
writeln(json);

// writeln不像構一樣自動格式化類
//或者重載`toString`,或者手寫.
writefln("Person(%s, %s, %s)", p.name, p.age, p.type);

/*
輸出:
{"age":20,"name":"Bradley","type":"Student"}
Person(Bradley, 20, Student)
*/
}
      

然後是,解序化:

T deserialise(T)(JSONValue json)
{
    ...
else static if(is(T == struct) || is(T == class)) //記得檢查類
    {
static if(is(T == class))
        {
if(json.type == JSONType.null_)
return null;//無效類型
T toReturn = new T();
        }
else
        {
T toReturn;
        }

/**/

return toReturn;
    }
else
    { /*略*/ }
}
      

測試​

​空類​

void main()
{
import std.stdio : writeln;
Person p = null;
auto json = p.serialise();
writeln(json);
writeln(json.deserialise!Person());
/*
輸出:
無效
無效
*/
}
      

目前用​

​new T()​

​建構類,僅在​

​無構造器/有預設構造器​

​時管用.而實際中,類可有​

​參數化構造函數,且不支援預設構造函數​

​.加上:

enum HasDefaultCtor(T) = __traits(compiles, new T());
      

判斷,是否有​

​預設構造器​

​.構造函數問題的​

​變通​

​,​

​事實類​

​一般​

​不公開​

​變量.

enum HasStaticDeserialiseFunc(T) = __traits(compiles, { T obj = T.deserialise(JSONValue()); });
//要檢查代碼在`括号`内.
      

​T.deserialise​

​解序化​

​為​

​靜态函數.傳回給​

​T​

​,檢查是否​

​相容T​

​,以​

​數格值​

​為第1參數.

現在,​

​解序化​

​是這樣的:

enum HasStaticDeserialiseFunc(T) = __traits(compiles, { T obj = T.deserialise(JSONValue()); });    

T deserialise(T)(JSONValue json)
{
    ...
/**/
else static if(is(T == struct) || is(T == class))
    {
static if(is(T == class))
        {
static assert(HasDefaultCtor!T || HasStaticDeserialiseFunc!T, 
"class `" ~ T.stringof ~ "`要求預設構造器或比對靜的" ~ T.stringof ~ " deserialise(JSONValue)`"
            ); //條件.用`靜态反序化`反序化
static if(HasDefaultCtor!T)
            {
T toReturn = new T();
            }//有預設構造
        }
/**/

return toReturn;
    }
else
    { /**/ }
}
      

外面:

//解序化/反序化
else static if(is(T == struct) || is(T == class))
{
static if(is(T == class))
    { /* 前面,處理無效 */ }
else
    { /**/ }//類的無效

static if(HasStaticDeserialiseFunc!T)
    {
return T.deserialise(json);
    }//類可`解序化`.
else //
    {
static foreach(/**/)
        {{
/**/
        }}
return toReturn;
    }
}
      
class Person
{
private
    {
string name;
int age;
PersonType type;
    }

// 無預設構造器
this(string name, int age, PersonType type)
    {
this.name = name;
this.age = age;
this.type = type;
    }

static Person deserialise(JSONValue value)
    {
// 必須自己實作`解序化`
return new Person(
value["name"].deserialise!string(),
value["age"].deserialise!int(),
value["type"].deserialise!PersonType()
        );
    }

// 顯示資訊
override string toString()
    {
import std.format : format;
return format("Person(%s, %s, %s)", this.name, this.age, this.type);
    }
}

void main()
{
import std.stdio : writeln;

auto person = new Person("Bradley", 20, PersonType.Student);
auto json = person.serialise();
writeln(json);
person = json.deserialise!Person();
writeln(person);

/*
輸出:
{"age":20,"name":"Bradley","type":"Student"}
Person(Bradley, 20, Student)
*/
}