简体   繁体   English

如何在ServiceStack.OrmLite中自定义复杂类型的序列化/反序列化

[英]How can I customize the serialization/deserialization of a complex type in ServiceStack.OrmLite

I am using ServiceStack.OrmLite to persist data in a SQLite database, and quite happy with it so far. 我使用ServiceStack.OrmLite将数据保存在SQLite数据库中,到目前为止对它非常满意。

However, many of my objects have properties of a complex type which I don't want serialized using JSV . 但是,我的许多对象都具有复杂类型的属性,我不希望使用JSV序列化。

I need to be able to specify a custom serialization/deserialization that should be used to store the property in the database (as a string). 我需要能够指定应该用于在数据库中存储属性的自定义序列化/反序列化(作为字符串)。 In the db4o world this would be equivalent to using the translation feature provided by IObjectConstructor . db4o世界中,这相当于使用IObjectConstructor提供的转换功能。

A good example of complex types that cannot be serialized and deserialized properly are NodaTime types, even though they can be easily mapped to strings (I already have the serialization/deserialization functions which I used with db4o ). 无法正确序列化和反序列化的复杂类型的一个很好的例子是NodaTime类型,即使它们可以很容易地映射到字符串(我已经有了与db4o使用的序列化/反序列化函数)。

What is the simplest way to achieve that? 实现这一目标的最简单方法是什么? A wrapper would not be very convenient as I would have to write and maintain one for each type that contains a property of this complex type. 包装器不是很方便,因为我必须为包含这种复杂类型属性的每种类型编写和维护一个包装器。

For those who may be interested in the wrapper pattern I am currently using to implement custom serialization with OrmLite (works with other ORMs too), here is a simple working example with NodaTime types that are otherwise not serialized properly: 对于那些可能对包装模式感兴趣的人,我目前正在使用OrmLite实现自定义序列化(也可以与其他ORM一起使用),这里有一个简单的工作示例,其中NodaTime类型没有正确序列化:

public class BusinessObject {
    public class Poco {
        public readonly BusinessObject BusinessObject;

        public Poco(BusinessObject businessObject) {
            this.BusinessObject = businessObject;
        }

        public Poco() {
            this.BusinessObject = new BusinessObject();
        }

        public string Id {
            get { return this.BusinessObject.Id; }
            set { this.BusinessObject.Id = value; }
        }

        public decimal Amount {
            get { return this.BusinessObject.Amount; }
            set { this.BusinessObject.Amount = value; }
        }

        public DateTime Dt {
            get { return this.BusinessObject.Dt.ToDateTime(); }
            set { this.BusinessObject.Dt = LocalDateTime.FromDateTime(value).Date; }
        }

        public string TimeZone {
            get { return this.BusinessObject.TimeZone.Id; }
            set { this.BusinessObject.TimeZone = DateTimeZoneProviders.Tzdb.GetZoneOrNull(value); }
        }

        public string Description {
            get { return this.BusinessObject.Description; }
            set { this.BusinessObject.Description = value; }
        }
    }

    public string Id { get; private set; }
    public decimal Amount { get; private set; }
    public LocalDate Dt { get; private set; }
    public DateTimeZone TimeZone { get; private set; }
    public string Description { get; private set; }

    public BusinessObject() { }

    public BusinessObject(string id, decimal amount, LocalDate dt, DateTimeZone timeZone, string description) {
        this.Id = id;
        this.Amount = amount;
        this.Dt = dt;
        this.TimeZone = timeZone;
        this.Description = description;
    }
}

I hope it will soon be possible to define hooks/callbacks for specific types that should be handled with custom code, and also that OrmLite will allow properties with private setters to be reloaded from persistence (currently it will only work in one direction). 我希望很快就可以为应该使用自定义代码处理的特定类型定义钩子/回调,并且OrmLite将允许具有私有setter的属性从持久性重新加载(目前它只能在一个方向上工作)。

Update (2014/03/08) : As a temporary workaround, it is possible to have OrmLite use custom serialization/deserialization by calling first: 更新(2014/03/08) :作为临时解决方法,可以通过先调用OrmLite使用自定义序列化/反序列化:

JsConfig<BusinessObject>.TreatValueAsRefType = true;

Even if BusinessObject is a reference type. 即使BusinessObject是引用类型。 Then, you can enjoy the beauty/simplicity/ubiquity of: 然后,您可以享受美丽/简单/无处不在:

JsConfig<BusinessObject>.RawSerializeFn = bo => bo.Serialize();
JsConfig<BusinessObject>.RawDeserializeFn = str => BusinessObject.Deserialize(str);

Hopefully support for custom mapping will be added soon (so that for example a NodaTime.LocalDate can be mapped to a DateTime instead of a string). 希望很快就会添加对自定义映射的支持(例如,可以将NodaTime.LocalDate映射到DateTime而不是字符串)。

OrmLite now supports pluggable text serializers . OrmLite现在支持可插入文本序列化程序

Pluggable serialization lets you specify different serialization strategies of Complex Types for each available RDBMS provider, eg: 可插入序列化允许您为每个可用的RDBMS提供程序指定复杂类型的不同序列化策略,例如:

//ServiceStack's JSON and JSV Format
SqliteDialect.Provider.StringSerializer = new JsvStringSerializer();       
PostgreSqlDialect.Provider.StringSerializer = new JsonStringSerializer();
//.NET's XML and JSON DataContract serializers
SqlServerDialect.Provider.StringSerializer = new DataContractSerializer();
MySqlDialect.Provider.StringSerializer = new JsonDataContractSerializer();
//.NET XmlSerializer
OracleDialect.Provider.StringSerializer = new XmlSerializableSerializer();

You can also provide a custom serialization strategy by implementing IStringSerializer : 您还可以通过实现IStringSerializer来提供自定义序列化策略:

public interface IStringSerializer
{
    To DeserializeFromString<To>(string serializedText);
    object DeserializeFromString(string serializedText, Type type);
    string SerializeToString<TFrom>(TFrom from);
}

To serialize complex types, set up your own serializer (and deserializer) on JsConfig : 要序列化复杂类型,请在JsConfig上设置自己的序列化程序(和反序列化程序):

JsConfig<Foo>.SerializeFn = foo => foo.ToString("XOXO", CultureInfo.InvariantCulture);
JsConfig<Foo>.DeSerializeFn = foo =>
{
    var result = Foo.Parse(foo, CultureInfo.InvariantCulture);
    return result;
};

You might also want to tell JsConfig to assume UTC dates: 您可能还想告诉JsConfig假设UTC日期:

JsConfig.Init(new Config {
    JsConfig.AssumeUtc = true
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM