From a9fcceafa051390b53a347fe2ced245c5711bb83 Mon Sep 17 00:00:00 2001 From: Denis Revunov Date: Mon, 16 Feb 2026 11:59:28 +0300 Subject: [PATCH] Support UUID and other stringlike types as keys --- src/write.jl | 7 ++++--- test/json.jl | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/write.jl b/src/write.jl index 2f1d7a2..475edf6 100644 --- a/src/write.jl +++ b/src/write.jl @@ -29,9 +29,11 @@ sizeguess(::Null) = 4 sizeguess(::Omit) = 0 sizeguess(_) = 512 +const StringLike = Union{Enum, AbstractChar, VersionNumber, Cstring, Cwstring, UUID, Dates.TimeType, Type, Logging.LogLevel} + StructUtils.lower(::JSONStyle, ::Missing) = nothing StructUtils.lower(::JSONStyle, x::Symbol) = String(x) -StructUtils.lower(::JSONStyle, x::Union{Enum, AbstractChar, VersionNumber, Cstring, Cwstring, UUID, Dates.TimeType, Type, Logging.LogLevel}) = string(x) +StructUtils.lower(::JSONStyle, x::StringLike) = string(x) StructUtils.lower(::JSONStyle, x::Regex) = x.pattern StructUtils.lower(::JSONStyle, x::AbstractArray{<:Any,0}) = x[1] StructUtils.lower(::JSONStyle, x::AbstractArray{<:Any, N}) where {N} = (view(x, ntuple(_ -> :, N - 1)..., j) for j in axes(x, N)) @@ -250,9 +252,8 @@ end StructUtils.lowerkey(::JSONStyle, s::AbstractString) = s StructUtils.lowerkey(::JSONStyle, sym::Symbol) = String(sym) -StructUtils.lowerkey(::JSONStyle, n::Union{Integer, Union{Float16, Float32, Float64}}) = string(n) +StructUtils.lowerkey(::JSONStyle, s::Union{StringLike, Real}) = string(s) StructUtils.lowerkey(::JSONStyle, x) = throw(ArgumentError("No key representation for $(typeof(x)). Define StructUtils.lowerkey(::JSON.JSONStyle, ::$(typeof(x)))")) - """ JSON.json(x) -> String JSON.json(io, x) diff --git a/test/json.jl b/test/json.jl index 8725b43..2df027f 100644 --- a/test/json.jl +++ b/test/json.jl @@ -27,6 +27,8 @@ end dropped::Union{Nothing, JSON.Omit} end +@enum JsonFruit Apple Orange + @testset "JSON.json" begin @testset "Basics" begin @@ -261,6 +263,18 @@ end @test JSON.json((a=1, b=nothing); omit_null=false) == "{\"a\":1,\"b\":null}" @test JSON.json((a=1, b=[]); omit_empty=true) == "{\"a\":1}" @test JSON.json((a=1, b=[]); omit_empty=false) == "{\"a\":1,\"b\":[]}" + @testset "All string-like types as keys" begin + date = Dates.DateTime(1970) + @test JSON.json([ + UUID(0) => "uuid", + 'c' => "char", + v"0.0.1" => "ver", + Apple => "Enum 1", + Orange => "Enum 2", + date => "date" + ]) == """{"00000000-0000-0000-0000-000000000000":"uuid","c":"char","0.0.1":"ver","Apple":"Enum 1","Orange":"Enum 2","1970-01-01T00:00:00":"date"}""" + end + @testset "Sentinel overrides" begin @test JSON.json(JSON.Null()) == "null" @test_throws ArgumentError JSON.json(JSON.Omit())