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 }