From f46c38aa1d25ad03cd7dcce6527daec58019d042 Mon Sep 17 00:00:00 2001 From: Karim Khaleel Date: Sun, 23 Mar 2025 00:20:01 -0400 Subject: [PATCH 1/2] Add KeyNamerWithOriginalFieldName naming function --- reflect.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/reflect.go b/reflect.go index 73ce7e4..673380f 100644 --- a/reflect.go +++ b/reflect.go @@ -140,6 +140,12 @@ type Reflector struct { // If a json tag is present, KeyNamer will receive the tag's name as an argument, not the original key name. KeyNamer func(string) string + // KeyNamerWithOriginalFieldName allows customizing of key names. + // This is like KeyNamer, except it passes in the name it potentially extracted from the json tag as well as + // the original field's name. Has no effect if KeyNamer set. + // First argument is the original go field name, second is the one extracted from the json tag + KeyNamerWithOriginalFieldName func(string, string) string + // AdditionalFields allows adding structfields for a given type AdditionalFields func(reflect.Type) []reflect.StructField @@ -1055,6 +1061,8 @@ func (r *Reflector) reflectFieldName(f reflect.StructField) (string, bool, bool, name = "" } else if r.KeyNamer != nil { name = r.KeyNamer(name) + } else if r.KeyNamerWithOriginalFieldName != nil { + name = r.KeyNamerWithOriginalFieldName(f.Name, jsonTags[0]) } return name, false, required, nullable From ad6be1f43c1f002cf326ac736bb584eb75b5fcad Mon Sep 17 00:00:00 2001 From: Karim Khaleel Date: Sun, 23 Mar 2025 00:21:35 -0400 Subject: [PATCH 2/2] Add KeyNamerWithOriginalFieldName tests --- fixtures/keynamed_with_original_names.json | 27 ++++++++++++++++++++++ reflect_test.go | 24 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 fixtures/keynamed_with_original_names.json diff --git a/fixtures/keynamed_with_original_names.json b/fixtures/keynamed_with_original_names.json new file mode 100644 index 0000000..77100b2 --- /dev/null +++ b/fixtures/keynamed_with_original_names.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/invopop/jsonschema/key-namer-with-original-field-named", + "$ref": "#/$defs/KeyNamerWithOriginalFieldNamed", + "$defs": { + "KeyNamerWithOriginalFieldNamed": { + "properties": { + "ThisWasLeftAsIs": { + "type": "string" + }, + "coming_from_json": { + "type": "boolean" + }, + "AAA": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "ThisWasLeftAsIs", + "coming_from_json", + "AAA" + ] + } + } +} \ No newline at end of file diff --git a/reflect_test.go b/reflect_test.go index 93bee67..c08ddfc 100644 --- a/reflect_test.go +++ b/reflect_test.go @@ -312,6 +312,12 @@ type KeyNamed struct { RenamedByComputation int `jsonschema_description:"Description was preserved"` } +type KeyNamerWithOriginalFieldNamed struct { + ThisWasLeftAsIs string + ComesFromJSON bool `json:"coming_from_json"` + A string `json:"bbb"` +} + type SchemaExtendTestBase struct { FirstName string `json:"FirstName"` LastName string `json:"LastName"` @@ -468,6 +474,24 @@ func TestSchemaGeneration(t *testing.T) { return "unknown case" }, }, "fixtures/keynamed.json"}, + {&KeyNamerWithOriginalFieldNamed{}, &Reflector{ + KeyNamerWithOriginalFieldName: func(fieldName string, tagName string) string { + key := fieldName + ":" + tagName + switch key { + case "ThisWasLeftAsIs:": + return fieldName + case "ComesFromJSON:coming_from_json": + return tagName + case "A:bbb": + b := strings.Builder{} + for i := 0; i < len(tagName); i++ { + b.WriteString(fieldName) + } + return b.String() + } + return "unknown case" + }, + }, "fixtures/keynamed_with_original_names.json"}, {MapType{}, &Reflector{}, "fixtures/map_type.json"}, {ArrayType{}, &Reflector{}, "fixtures/array_type.json"}, {SchemaExtendTest{}, &Reflector{}, "fixtures/custom_type_extend.json"},