Base.serialize
和 Base.deserialize
的默认实现为整个给定对象执行序列化/反序列化。
从序列化中排除字段并仍然能够正确反序列化它的正确方法是什么?
这是一个简化的代码示例:
# The target struct
struct Foo
x::Int
y::Union{Int, Void} #we do not want to serialize this field
end
foo1 = Foo(1,2)
# Serialization
write_iob = IOBuffer()
serialize(write_iob, foo1)
seekstart(write_iob)
content = read(write_iob)
# Deserialization
read_iob = IOBuffer(content)
foo2 = deserialize(read_iob)
@show foo1
@show foo2
以上代码的输出为:
foo1 = Foo(1, 2)
foo2 = Foo(1, 2)
期望的结果应该是:
foo1 = Foo(1, 2)
foo2 = Foo(1, nothing)
在这里,我假设我们可以为缺失的字段定义一个默认值,例如,nothing
用于上面输出中的 y
。
最佳答案
在深入研究了我当前版本的 Julia (0.6.2) 中序列化/反序列化的实现之后,我找到了一个解决方案。以下是适用于问题示例的解决方案:
# Custom Serialization of a Foo instance
function Base.Serializer.serialize(s::AbstractSerializer, instance::Foo)
Base.Serializer.writetag(s.io, Base.Serializer.OBJECT_TAG)
Base.Serializer.serialize(s, Foo)
Base.Serializer.serialize(s, instance.x)
end
# Custom Deserialization of a Foo instance
function Base.Serializer.deserialize(s::AbstractSerializer, ::Type{Foo})
x = Base.Serializer.deserialize(s)
Foo(x,nothing)
end
现在,如果您再次运行测试代码:
# The target struct
struct Foo
x::Int
y::Union{Int, Void} #we do not want to serialize this field
end
foo1 = Foo(1,2)
# Serialization
write_iob = IOBuffer()
serialize(write_iob, foo1)
seekstart(write_iob)
content = read(write_iob)
# Deserialization
read_iob = IOBuffer(content)
foo2 = deserialize(read_iob)
@show foo1
@show foo2
测试代码输出:
foo1 = Foo(1, 2)
foo2 = Foo(1, nothing)
我应该指出,上述解决方案取决于序列化/反序列化的当前实现(在 Julia 0.6.2 中),并且不能保证其 future 的稳定性。因此,我会继续关注寻找更好的解决方案。
更新:上述代码在 Julia 1.0 之后不起作用。这是更新后的代码:
using Serialization
# The target struct
struct Foo
x::Int
y::Union{Int, Nothing} #we do not want to serialize this field
end
# Custom Serialization of a Foo instance
function Serialization.serialize(s::AbstractSerializer, instance::Foo)
Serialization.writetag(s.io, Serialization.OBJECT_TAG)
Serialization.serialize(s, Foo)
Serialization.serialize(s, instance.x)
end
# Custom Deserialization of a Foo instance
function Serialization.deserialize(s::AbstractSerializer, ::Type{Foo})
x = Serialization.deserialize(s)
Foo(x,nothing)
end
foo1 = Foo(1,2)
# Serialization
write_iob = IOBuffer()
serialize(write_iob, foo1)
seekstart(write_iob)
content = read(write_iob)
# Deserialization
read_iob = IOBuffer(content)
foo2 = deserialize(read_iob)
@show foo1
@show foo2
关于serialization - 如何在 Julia 中为结构实现自定义序列化/反序列化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49007433/