i'm using a format that is a lot like the top level structure of Wurth family languages (of which Go is pretty much one)
binary format is for databases, and not really advised for wire formats, for reasons of needing a lot more tools to just simply make sense of data that is sent on the wire.
json is a horrible, "natural language" similar structure. it's not line structured, it is riddled with brackets, parentheses and interstitial comma separators. just that one point alone costs an extra step in the logic of parsing or marshaling to not put a separator after the last field.
nah, the event format looks like this:
PUBKEY:
TIMESTAMP:
CONTENT:
TAG:key:value (values can also be binary, with the same prefix as above)
... any number more tags
SIGNATURE:
the order of fields is fixed, and everything up to the newline before SIGNATURE derives the event ID hash, so that is also left out, it is only needed once the message has been received, and even in the database a truncated hash of the ID is used as an index, as the client knows the hash. also i make a dedicated index just for getting those ID hashes directly from other index references to the database sequence number of the event, so i can return the ID and not decode the event (it's in a fast binary format) or i can instead seek to the event by its serial number and return the whole event (so i can make query syntax that requests either the whole events or a whole huge number of event IDs so the raw event can be fetched on demand
anyway, that's the general gist of what i'm working with. line separated makes scanning passes a lot simpler to write than bracket syntax, brackets and quotes (even worse for escaping) both require multi-level state machines, that spec as you can see above, you can do a quick and dirty parser that just splits by lines, then splits reading forward by semicolons, and you have all the data except for decoding the binary fields. and yes, you can also quickly scan to get the event body, everything down to the signature, just by counting newlines and reading the first few characters, in fact, as they can be distinguished just by two characters, following a newline character.
i hope that gives you some ideas, anyway. i have written advanced (even JSON) state machines for unmarshalling but they are very long, like 400 lines of code, and that's not necessarily enough because you have to handle string escaping and you also have to handle arbitrary whitespace for pretty printed forms.
that's the thing about the format i designed. it doesn't need a pretty printed form, it is readable already, because it uses line breaks and sentinels, you can scan it visually also to recognise its elements, same reason it's easy to see what is what, it's easy to write code that sees what is what.
i mean, the whole business with commas and lists has a whole subject in the field of language syntax, the oxford and cambridge and whatever other idioms of writing shit in human languages.
in the olden days, when computers were slow, small and shitty, people designed simple formats for data that were both simple to read and simple to parse. good old Jevon's paradox at work, making lazy humans make "pretty" things with "sophisticated" syntax because "oh, it's ok, the processors are cheap and fast now"
just compile a large (25mb source+) Go project and compare it with a similar build process for a Rust or C++ or even C compilation. you look away, and Go is finished. The others, you have time to cook breakfast, drink a whole coffee and forget what you were doing on the PC

