diff --git a/Project.toml b/Project.toml index 852b0ce..ae93f1c 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Serde" uuid = "db9b398d-9517-45f8-9a95-92af99003e0e" -version = "2.0.0" +version = "3.0.0" [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" diff --git a/src/Ser/Ser.jl b/src/Ser/Ser.jl index de29db4..d694a83 100644 --- a/src/Ser/Ser.jl +++ b/src/Ser/Ser.jl @@ -1,5 +1,13 @@ # Ser/Ser +(ser_name(::Type{T}, ::Val{x})::Symbol) where {T,x} = x +(ser_value(::Type{T}, ::Val{x}, v::V)::V) where {T,x,V} = v +(ser_type(::Type{T}, v::V)::V) where {T,V} = v + +(ignore_field(::Type{T}, ::Val{x})::Bool) where {T,x} = false +(ignore_field(::Type{T}, k::Val{x}, v::V)::Bool) where {T,x,V} = ignore_field(T, k) +(ignore_null(::Type{T})::Bool) where {T} = true + include("SerCsv.jl") using .SerCsv diff --git a/src/Ser/SerJson.jl b/src/Ser/SerJson.jl index 66cf907..892f82c 100644 --- a/src/Ser/SerJson.jl +++ b/src/Ser/SerJson.jl @@ -4,6 +4,11 @@ export to_json export to_pretty_json using Dates +import ..ser_name, + ..ser_value, + ..ser_type, + ..ignore_null, + ..ignore_field const JSON_NULL = "null" const INDENT = " " @@ -155,20 +160,11 @@ function json_value!(buf::IOBuffer, f::Function, val::AbstractSet; l::Int64, kw. return print(buf, indent(l - 1), "]") end -(ser_name(::Type{T}, ::Val{x})::Symbol) where {T,x} = x -(ser_value(::Type{T}, ::Val{x}, v::V)::V) where {T,x,V} = v -(ser_type(::Type{T}, v::V)::V) where {T,V} = v - (isnull(::Any)::Bool) = false (isnull(v::Missing)::Bool) = true (isnull(v::Nothing)::Bool) = true (isnull(v::Float64)::Bool) = isnan(v) || isinf(v) -(ignore_null(::Type{T})::Bool) where {T} = false - -(ignore_field(::Type{T}, ::Val{x})::Bool) where {T,x} = false -(ignore_field(::Type{T}, k::Val{x}, v::V)::Bool) where {T,x,V} = ignore_field(T, k) - function json_value!(buf::IOBuffer, f::Function, val::T; l::Int64, kw...)::Nothing where {T} next = iterate(f(T)) print(buf, "{", indent(l)) diff --git a/src/Ser/SerQuery.jl b/src/Ser/SerQuery.jl index e24f0aa..50f6f4c 100644 --- a/src/Ser/SerQuery.jl +++ b/src/Ser/SerQuery.jl @@ -2,13 +2,15 @@ module SerQuery export to_query +import ..ser_name, + ..ser_value, + ..ser_type, + ..ignore_null, + ..ignore_field + function _bytes end function escape_query end -(ser_name(::Type{T}, ::Val{x})::Symbol) where {T,x} = x -(ser_value(::Type{T}, ::Val{x}, v::V)::V) where {T,x,V} = v -(ser_type(::Type{T}, v::V)::V) where {T,V} = v - (ignore_null(::Type{T})::Bool) where {T} = true isnull(::Any)::Bool = false @@ -94,7 +96,7 @@ end function iter_query(f::Function, query::Q)::Nothing where {Q} for field in fieldnames(Q) v = ser_type(Q, ser_value(Q, Val(field), getfield(query, field))) - if ignore_null(Q) && isnull(v) + if ignore_null(Q) && isnull(v) || ignore_field(Q, Val(field), v) continue end field = string(ser_name(Q, Val(field))) diff --git a/src/Ser/SerToml.jl b/src/Ser/SerToml.jl index daacc9f..f321ebf 100644 --- a/src/Ser/SerToml.jl +++ b/src/Ser/SerToml.jl @@ -3,6 +3,11 @@ module SerToml export to_toml using Dates +import ..ser_name, + ..ser_value, + ..ser_type, + ..ignore_null, + ..ignore_field struct TomlSerializationError <: Exception message::String @@ -139,23 +144,17 @@ function toml_pairs(val::AbstractDict; kw...) return sort([(k, v) for (k, v) in val], by = x -> !issimple(x[2])) end -(ser_name(::Type{T}, ::Val{x})::Symbol) where {T,x} = x -(ser_value(::Type{T}, ::Val{x}, v::V)::V) where {T,x,V} = v -(ser_type(::Type{T}, v::V)::V) where {T,V} = v - isnull(::Any) = false isnull(v::Missing)::Bool = true isnull(v::Nothing)::Bool = true -(ignore_null(::Type{T})::Bool) where {T} = true - function toml_pairs(val::T; kw...) where {T} kv = Tuple[] for field in fieldnames(T) k = ser_name(T, Val(field)) v = ser_type(T, ser_value(T, Val(field), getfield(val, field))) - if ignore_null(T) && isnull(v) + if (isnull(v) || ignore_field(T, Val(field), v)) continue end push!(kv, (k, v)) diff --git a/src/Ser/SerXml.jl b/src/Ser/SerXml.jl index 54584d9..f84ee7a 100644 --- a/src/Ser/SerXml.jl +++ b/src/Ser/SerXml.jl @@ -3,6 +3,11 @@ module SerXml export to_xml using Dates +import ..ser_name, + ..ser_value, + ..ser_type, + ..ignore_null, + ..ignore_field const CONTENT_WORD = "_" @@ -74,23 +79,23 @@ xml_key(val::Symbol; kw...)::String = xml_key(string(val); kw...) # pair function xml_pair(key, val::AbstractString; level::Int64, kw...)::String - return shift(level) * - "<" * xml_key(key; kw...) * ">" * - xml_value(val) * + return shift(level) * + "<" * xml_key(key; kw...) * ">" * + xml_value(val) * "" * "\n" end function xml_pair(key, val::Symbol; level::Int64, kw...)::String return shift(level) * - "<" * xml_key(key; kw...) * ">" * - xml_value(val) * + "<" * xml_key(key; kw...) * ">" * + xml_value(val) * "" * "\n" end function xml_pair(key, val::Number; level::Int64, kw...)::String - return shift(level) * - "<" * xml_key(key; kw...) * ">" * - xml_value(val) * + return shift(level) * + "<" * xml_key(key; kw...) * ">" * + xml_value(val) * "" * "\n" end @@ -99,10 +104,10 @@ function xml_pair(key, val::AbstractVector{T}; level::Int64, kw...)::String wher for el in val if issimple(el) push!( - buf, - shift(level) * - "<" * xml_key(key; kw...) * ">" * - xml_value(el) * + buf, + shift(level) * + "<" * xml_key(key; kw...) * ">" * + xml_value(el) * "" * "\n", ) else @@ -116,10 +121,10 @@ function xml_pair(key, val::AbstractDict; level::Int64, kw...)::String tags, cont = nodes(val), content(val) return if isempty(tags) && isempty(cont) shift(level) * "<" * xml_key(key; kw...) * attribute_xml(val) * "/>" * "\n" - elseif isempty(cont) - shift(level) * - "<" * xml_key(key; kw...) * attribute_xml(val) * ">" * - "\n" * _to_xml(tags; level = level + 1) * shift(level) * + elseif isempty(cont) + shift(level) * + "<" * xml_key(key; kw...) * attribute_xml(val) * ">" * + "\n" * _to_xml(tags; level = level + 1) * shift(level) * "" * "\n" else shift(level) * @@ -133,29 +138,23 @@ function xml_pairs(val::AbstractDict; kw...) return [(k, v) for (k, v) in val] end -(ser_name(::Type{T}, ::Val{x})::Symbol) where {T,x} = x -(ser_value(::Type{T}, ::Val{x}, v::V)::V) where {T,x,V} = v -(ser_type(::Type{T}, v::V)::V) where {T,V} = v - (isnull(::Any)::Bool) = false (isnull(v::Missing)::Bool) = true (isnull(v::Nothing)::Bool) = true -(ignore_null(::Type{T})::Bool) where {T} = true - function xml_pair(key, val::T; level::Int64, kw...)::String where {T} tags, cont = nodes(val), content(val) return if isempty(tags) && isempty(cont) shift(level) * "<" * xml_key(key; kw...) * attribute_xml(val) * "/>" * "\n" elseif isempty(cont) - shift(level) * - "<" * xml_key(key; kw...) * attribute_xml(val) * ">" * "\n" * - _to_xml(tags; level = level + 1) * shift(level) * + shift(level) * + "<" * xml_key(key; kw...) * attribute_xml(val) * ">" * "\n" * + _to_xml(tags; level = level + 1) * shift(level) * "" * "\n" else - shift(level) * - "<" * xml_key(key; kw...) * attribute_xml(val) * ">" * - cont * _to_xml(tags; level = level + 1) * + shift(level) * + "<" * xml_key(key; kw...) * attribute_xml(val) * ">" * + cont * _to_xml(tags; level = level + 1) * "" * "\n" end end diff --git a/src/Ser/SerYaml.jl b/src/Ser/SerYaml.jl index 0dd55c1..fbdd083 100644 --- a/src/Ser/SerYaml.jl +++ b/src/Ser/SerYaml.jl @@ -3,6 +3,11 @@ module SerYaml export to_yaml using Dates +import ..ser_name, + ..ser_value, + ..ser_type, + ..ignore_null, + ..ignore_field const YAML_NULL = "null" const INDENT = " " @@ -186,20 +191,11 @@ function yaml_value!(buf::IOBuffer, f::Function, val::AbstractSet; l::Int64, ski return print(buf) end -(ser_name(::Type{T}, ::Val{x})::Symbol) where {T,x} = x -(ser_value(::Type{T}, ::Val{x}, v::V)::V) where {T,x,V} = v -(ser_type(::Type{T}, v::V)::V) where {T,V} = v - (isnull(::Any)::Bool) = false (isnull(v::Missing)::Bool) = true (isnull(v::Nothing)::Bool) = true (isnull(v::Float64)::Bool) = isnan(v) || isinf(v) -(ignore_null(::Type{T})::Bool) where {T} = false - -(ignore_field(::Type{T}, ::Val{x})::Bool) where {T,x} = false -(ignore_field(::Type{T}, k::Val{x}, v::V)::Bool) where {T,x,V} = ignore_field(T, k) - function yaml_value!(buf::IOBuffer, f::Function, val::T; l::Int64, skip_lf::Bool = false, kw...)::Nothing where {T} next = iterate(f(T)) print(buf, skip_lf ? "" : indent(l)) diff --git a/src/Utl/Macros.jl b/src/Utl/Macros.jl index baee9c6..2a5a099 100644 --- a/src/Utl/Macros.jl +++ b/src/Utl/Macros.jl @@ -16,9 +16,9 @@ function chain(::Val{Symbol("@de_name")}, struct_name::Symbol, field_key::String end end -function chain(::Val{Symbol("@ser_json_name")}, struct_name::Symbol, field_key::String, ser_custom_name::Any)::Expr +function chain(::Val{Symbol("@ser_name")}, struct_name::Symbol, field_key::String, ser_custom_name::Any)::Expr return quote - function Serde.SerJson.ser_name(::Type{T}, ::Val{Symbol($field_key)}) where {T<:$struct_name} + function Serde.ser_name(::Type{T}, ::Val{Symbol($field_key)}) where {T<:$struct_name} return $ser_custom_name end end @@ -31,7 +31,7 @@ Helper macro that implements user friendly configuration of the (de)serializatio Available `decorators`: - `@default_value`: Used to define default values for fields of declared type (see [`Serde.default_value`](@ref)). - `@de_name`: Used to defines an alias names for fields of declared type (see [`Serde.custom_name`](@ref)). -- `@ser_json_name`: Used to define custom output name for fields of declared type (see [`Serde.ser_name`](@ref ser_name)). +- `@ser_name`: Used to define custom output name for fields of declared type (see [`Serde.ser_name`](@ref ser_name)). Next, the syntax template looks like this: ```julia @serde @decor_1 @decor_2 ... struct @@ -46,7 +46,7 @@ Decorator values belonging to a certain field must be separated by the `|` symbo ## Examples ```julia -@serde @default_value @de_name @ser_json_name mutable struct Foo +@serde @default_value @de_name @ser_name mutable struct Foo bar::Int64 | 1 | "first" | "bar" baz::Int64 | 2 | "baz" | "second" end @@ -62,7 +62,7 @@ Also, now names from the `@de_name` column will be used for deserialization. julia> deser_json(Foo, \"\"\"{"first": 30}\"\"\") Foo(30, 2) ``` -Names from the `@ser_json_name` column will be used as output names for serialization. +Names from the `@ser_name` column will be used as output names for serialization. ```julia-repl julia> to_json(Foo(40, 50)) |> print {"bar":40,"second":50}