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)
    */
}
posted @   zjh6  阅读(9)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示