From c1b23af63a399f90af76cb32c448c3f5819e9cf8 Mon Sep 17 00:00:00 2001 From: ErikPelli Date: Wed, 25 May 2022 16:36:29 +0200 Subject: [PATCH] feat: support automatic camel case field key Add camel case encoding option Add camel case key conversion Add camel case test --- encode_test.go | 26 ++++++++++++++++++++++++++ internal/encoder/option.go | 3 ++- internal/encoder/vm/util.go | 13 ++++++++++++- option.go | 7 +++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/encode_test.go b/encode_test.go index 92f4304..5f36231 100644 --- a/encode_test.go +++ b/encode_test.go @@ -2388,3 +2388,29 @@ func TestIssue324(t *testing.T) { t.Fatalf("failed to encode. expected %q but got %q", expected, got) } } + +func TestIssue271(t *testing.T) { + type T struct { + FieldA bool + } + + type T2 struct { + FieldA bool `json:"fieldA"` + } + + v := T{FieldA: true} + got, err := json.MarshalWithOption(v, json.EnableCamelCase()) + if err != nil { + t.Fatal(err) + } + + v2 := T2{FieldA: true} + expected, err := json.Marshal(v2) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(expected, got) { + t.Fatalf("failed to encode. expected %q but got %q", expected, got) + } +} diff --git a/internal/encoder/option.go b/internal/encoder/option.go index 82d5ce3..db3a434 100644 --- a/internal/encoder/option.go +++ b/internal/encoder/option.go @@ -5,7 +5,7 @@ import ( "io" ) -type OptionFlag uint8 +type OptionFlag uint16 const ( HTMLEscapeOption OptionFlag = 1 << iota @@ -16,6 +16,7 @@ const ( ContextOption NormalizeUTF8Option FieldQueryOption + CamelCaseOption ) type Option struct { diff --git a/internal/encoder/vm/util.go b/internal/encoder/vm/util.go index 86291d7..a1cb51c 100644 --- a/internal/encoder/vm/util.go +++ b/internal/encoder/vm/util.go @@ -3,6 +3,7 @@ package vm import ( "encoding/json" "fmt" + "unicode" "unsafe" "github.com/goccy/go-json/internal/encoder" @@ -184,7 +185,17 @@ func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte { return append(b, '{') } -func appendStructKey(_ *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { +func appendStructKey(e *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte { + if e.Option.Flag&encoder.CamelCaseOption > 0 { + key := []rune(code.Key) + for i := range key { + if unicode.IsLetter(key[i]) { + key[i] = unicode.ToLower(key[i]) + break + } + } + return append(b, string(key)...) + } return append(b, code.Key...) } diff --git a/option.go b/option.go index af400a4..bba4f74 100644 --- a/option.go +++ b/option.go @@ -24,6 +24,13 @@ func DisableHTMLEscape() EncodeOptionFunc { } } +// EnableCamelCase convert the keys to camel case when encoding a struct. +func EnableCamelCase() EncodeOptionFunc { + return func(opt *EncodeOption) { + opt.Flag |= encoder.CamelCaseOption + } +} + // DisableNormalizeUTF8 // By default, when encoding string, UTF8 characters in the range of 0x80 - 0xFF are processed by applying \ufffd for invalid code and escaping for \u2028 and \u2029. // This option disables this behaviour. You can expect faster speeds by applying this option, but be careful.