odin-lang / Odin

Odin Programming Language
https://odin-lang.org
BSD 3-Clause "New" or "Revised" License
6.92k stars 611 forks source link

Json should allow a way to specify how to marshal/unmarshal an object (e.g. encoding/uuid) #4257

Open edyu opened 1 month ago

edyu commented 1 month ago

PLEASE POST THIS IN THE DISCUSSION TAB UNDER "PROPOSALS" OR "IDEAS/REQUESTS"

Is your feature request related to a problem? Please describe. uuids are being used more and more often as id and when writing or reading from json, it's much better to use the string format of the uuid which is a string of the format 8-4-4-4-12. However due to implementation detail, uuid.Identifier is basically distinct [16]u8 which when printing or marshalling, it's basically an array of bytes that is not only long but also difficult to discern. Contrast [16]u8 [38,101,146,205,150,13,64,145,152,28,140,37,196,75,16,24] with string 266592cd-960d-4091-981c-8c25c44b1018

Describe the solution you'd like A generic solution would be something similar to how fmt allows you to use either fmt:"s" in the struct and then overwrite behavior with User_Formatter. It would be great if json has/reuses the similar ideas.

Otherwise, it would be great if we can just get uuid to be able to marshal/unmarshal to json and printing to fmt using the string format while still maintaining maybe a binary format such as distinct [16]u8 internally.

Additional context I'm using uuid as the id field of multiple structs and I'm also writing a rest api which uses the id to specify which resource to start/stop etc.

flysand7 commented 1 month ago

Other potential uses for custom field formatters in JSON:

  1. Decoding and encoding RFC-3339 timestamps into/from datetime.Date, datetime.DateTime, datetime.Ordinal or time.Time, like javascript seems to be doing.
  2. Decoding and encoding numbers into/from 64-bit and 128-bit integers. Some javascript libraries also do this, especially when transmitting
  3. Decoding and encoding strings into/from enum variants using a custom mapping.

In short, having custom field sub-marshallers would help solve the problem of having different platform-specific extensions that could normally require writing a custom JSON decoder, or decoding it in stages. JSON is a common interchange format and it's not uncommon for it to be extended in ever so slightly different ways to allow for custom extensions.

I'm not entirely familiar with json marshalling code so I don't know about implications of including this sort of custom handling into the code.

edyu commented 1 month ago

Oh yeah, time, datetime, timestamp would totally be great if we can marshal/unmarshal them in a particular format rather than just numbers. I totally agree with @flysand7

edyu commented 1 month ago

Just want to put a note on RFC-3339. I'm now encountering the problem with strings containing RFC-3339 throwing error:

Unsupported_Type_Error{id = Time, token = Token{pos = Pos{offset = 314, line = 1, column = 314}, kind = "String", text = "\"2024-09-30T16:06:27.549047156Z\""}}