Документация Engee

Пользовательская сериализация

API достаточно прост: чтобы обеспечить пользовательскую сериализацию для типа A, вы определяете новый тип, например ASerialization, содержащий поля, которые следует хранить, и определяете JLD2.writeas(::Type{A}) = ASerialization. На внутреннем уровне JLD2 вызывает функцию Base.convert при записи и загрузке, поэтому ее следует расширить для вашего типа.

struct A
    x::Int
end

struct ASerialization
    x::Vector{Int}
end

JLD2.writeas(::Type{A}) = ASerialization
Base.convert(::Type{ASerialization}, a::A) = ASerialization([a.x])
Base.convert(::Type{A}, a::ASerialization) = A(only(a.x))

Будьте осторожны: некоторые внутренние типы Julia уже используют CustomSerialization, и JLD2.jl не поддерживает их вложение. Во избежание неожиданного поведения следует определить тип-оболочку наподобие ASerialization в примере выше, даже если подошел бы простой встроенный тип Julia (Vector{Int} в данном случае). Если вы не хотите перегружать функцию Base.convert, вместо этого можно определить

JLD2.wconvert(::Type{ASerialization}, a::A) = ASerialization([a.x])
JLD2.rconvert(::Type{A}, a::ASerialization) = A(only(a.x))

Это может быть особенно полезно, если соответствующие типы определены не вами.

struct B
    x::Float64
end

JLD2.writeas(::Type{B}) = Float64
JLD2.wconvert(::Type{Float64}, b::B) = b.x
JLD2.rconvert(::Type{B}, x::Float64) = B(x)

arr = [B(rand()) for i=1:10]

@save "test.jld2" arr

В данном примере перед сохранением данных на диске JLD2 преобразует массив структур B в обычный вектор Vector{Float64}.