Skip to content

json.% should serialize enum as number (ord), not string #17996

@timotheecour

Description

@timotheecour

enums should serialize as number (via ord), not string:

  • more compact json representation, more efficient serialization and deserialization
  • more stable (changing enum layout is typically more of a breaking change than changing enum string representation)
  • doesn't depend on a symbol table; eg some imports which could modify `$`(MyEnum), which supposes serializer and deserializer are consistent wrt $MyEnum; that's an important point!
  • supports roundtrip serialization, unlike with string representation which can't handle cases like this:
# compiler/lineinfos.nim:
type
  TMsgKind* = enum
    warnUser = "User"
    hintUser = "User"

the only con is human readability, which is arguably less important for something meant for serialization / network exchange, in particular it is less important than above points.

Example

depending on $ in scope suffers from the classical generic sandwich problem:

# t12265.nim:
when true:
  import std/json
  import t12265b
  import t12265c
  echo %f1

# t12265c.nim:
import t12265b
import std/json
proc `$`(a: Foo): string = "Foo_" & $a.ord
when defined caseDifferent:
  let a = %f0

# t12265b.nim:
type Foo* = enum f0, f1, f2

it also means it depends on order of imports, so unrelated code changes in 3rd party packages can break how an enum is serialized/deserialized

Current Output

nim r t12265.nim
"f1"

nim r -d:caseDifferent t12265.nim
"Foo_1"

Expected Output

these shouldn't differ.
With suggested change (serialize enum as number via ord), they wouldn't differ.

Possible Solution

  • serialize enum as number via ord, with -d:nimLegacyJsonEnum for a transition period; also change json.to to support reverse direction
  • or give up and recommend std/jsonutils for serialization/deserialization, and start deprecating (or at least soft-deprecating for now) json.%, json.to (jsonutils depends on it only in some parts and those parts could be refactored)

Additional Information

1.5.1 2c2ec48

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions