Lowercase JSON key names with JSON Marshal in Go
Asked Answered
K

4

225

I wish to use the "encoding/json" package to marshal a struct declared in one of the imported packages of my application.

Eg.:

type T struct {
    Foo int
}

Because it is imported, all available (exported) fields in the struct begins with an upper case letter. But I wish to have lower case key names:

out, err := json.Marshal(&T{Foo: 42})

will result in

{"Foo":42}

but I wish to get

{"foo":42}

Is it possible to get around the problem in some easy way?

Kraul answered 27/7, 2012 at 18:46 Comment(3)
@Zippoxer: I would say: a key in a client/server communication protocol strictly defined to lower case letters. Well, in my case it doesn't matter since I have defined the protocol myself.. but in theory at least? But, I know it is mainly just me spending too much time on a silly little detail.Kraul
Don't apologize. You're not the silly one, the language that does not accept the full json spec is the silly one (although the issue is easily solved, as below).Satirical
@ANisus: I misread your question as about struct key names, not JSON key names. Retracted the vote.Baumann
K
337

Have a look at the docs for encoding/json.Marshal. It discusses using struct field tags to determine how the generated json is formatted.

For example:

type T struct {
    FieldA int    `json:"field_a"`
    FieldB string `json:"field_b,omitempty"`
}

This will generate JSON as follows:

{
    "field_a": 1234,
    "field_b": "foobar"
}
Koziel answered 27/7, 2012 at 19:14 Comment(8)
Field tags? Oh my.. I missed this entire part when searching in the docs. I was looking for flags, functions or some other settings. Well, this is the exact answer I was looking for! And in addition, I have a new Go concept to learn about: field tags :)Kraul
They are quite handy. You can access them at runtime through the reflect package.Koziel
Yeah, when working with reflection I see how having a way to add meta data to a field can be a wonderful thing! Btw, just tried the answer. Works like a charm.Kraul
I've just started to curse the go language - how stupid is this, why would they make the fields with lowercase letters in the generated JSON etc, etc. Then I came across this thread and thought "OMG That's brilliant!!!". I even jumped and explained my girlfriend why I am so excited :D It's so cool :)))Spermatophore
Make sure there is no space between the colon and the first quotation mark of the tag! Use json:"some_tag" instead of json: "some_tag". I got bit by this for a while.Looselimbed
This could be made even better with some inspiration from Gson, which allows setting any "field naming policy" like LOWER_CASE_WITH_UNDERSCORES (aka snake case).Decimate
why is golang so trival to write a jsonRiboflavin
i don't get why this is an accepted answer. The OP's question was to output lowercased json keys for a struct that does not contain 'json' tags. every other language's serializer supports configuration of the output. it's not reasonable to expect that the input's type will be adjusted to satisfy marshaller's needs just because it cannot do any better than taking the field's name as-isLudicrous
V
10

You could make your own struct with the keys that you want to export, and give them the appropriate json tags for lowercase names. Then you can copy the desired struct into yours before encoding it as JSON. Or if you don't want to bother with making a local struct you could probably make a map[string]interface{} and encode that.

Villous answered 27/7, 2012 at 19:11 Comment(3)
The silly thing is that the other package (containing the types) is actually mine as well. But, yes, I have probably stared to blindly at the fact that it must be a struct. Using a map[string]interface{} would work as long as I don't end up with nested objects/structsKraul
@ANisus: Oh, my answer was predicated on you not being in control of the definition of the struct. jimt's answer is definitely what you want.Villous
Yeah, I wasn't clear whether or not it was an external package or not. But your answer is still relevant and useful in the cases when you don't control the definitions.Kraul
N
6

I will only add that you can generate those tags automatically using gopls. It is a menial task to add the tags manually, especially with large json structs, so the feature is a live-saver.

Adding the gopls langserver differs based on one's preferred editor. After:

go install golang.org/x/tools/gopls@latest

For Neovim with CoC you can :CocInstall coc-go and then go.tags.add. For complete docs on the CoC extension for go please see here.

Newsreel answered 28/5, 2022 at 21:1 Comment(3)
This could be a great answer if you simply tell how to do it. I know someone can google it. But showing how to achieve it would actually answer the question.Neighborhood
True. However, depending on the question author's preferred editor the implementation steps for generating the tags using gopls might differ. Hence, I skipped them.Newsreel
In VSCode, you can open the command panel (Cmd + Shift + p), and seach "Add tags" after this setup.Anglicist
M
0

You can generate the json:"camelCase" tags of struct fields with fatih/gomodifytags.

e.g.

$ gomodifytags -file main.go -struct T -add-tags json -transform camelcase -quiet -w

NB: You can also use -override to override existing tags.

Meyerhof answered 9/1, 2023 at 23:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.