lowercase_camel_json.go (1636B)
1 // Copyright 2019 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package parser
15
16 import (
17 "bytes"
18 "encoding/json"
19 "regexp"
20 "unicode"
21 "unicode/utf8"
22 )
23
24 // Regexp definitions
25 var (
26 keyMatchRegex = regexp.MustCompile(`\"(\w+)\":`)
27 wordBarrierRegex = regexp.MustCompile(`(\w)([A-Z])`)
28 )
29
30 // Code adapted from https://gist.github.com/piersy/b9934790a8892db1a603820c0c23e4a7
31 type LowerCaseCamelJSONMarshaller struct {
32 Value any
33 }
34
35 func (c LowerCaseCamelJSONMarshaller) MarshalJSON() ([]byte, error) {
36 marshalled, err := json.Marshal(c.Value)
37
38 converted := keyMatchRegex.ReplaceAllFunc(
39 marshalled,
40 func(match []byte) []byte {
41 // Attributes on the form XML, JSON etc.
42 if bytes.Equal(match, bytes.ToUpper(match)) {
43 return bytes.ToLower(match)
44 }
45
46 // Empty keys are valid JSON, only lowercase if we do not have an
47 // empty key.
48 if len(match) > 2 {
49 // Decode first rune after the double quotes
50 r, width := utf8.DecodeRune(match[1:])
51 r = unicode.ToLower(r)
52 utf8.EncodeRune(match[1:width+1], r)
53 }
54 return match
55 },
56 )
57
58 return converted, err
59 }