Skip to content

Commit

Permalink
refactor: change time.Time field output type
Browse files Browse the repository at this point in the history
  • Loading branch information
rsfreitas committed May 2, 2023
1 parent d5d64c0 commit f8ebee7
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 37 deletions.
52 changes: 24 additions & 28 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,25 @@ import (

const timeStringKind = "time.Time"

/*
Parse receives anything and tries to parse it to a JSON schema-like representation
that has the same type as the input.
For example, if the input is a struct, the output will be a map with the same fields
and nested types as the input struct.
If the input is a slice or array, the output will be a slice of the same length
containing the JSON schema-like representation of each element in the input.
If the input is a map, the output will be a map with the same keys and nested types
as the input map.
If the input is a pointer to a struct, slice, or map, the output will be a pointer to
the corresponding JSON schema-like representation.
For other types (e.g. bool, string, int), the output will be the type name as a string.
The function returns an interface{} value that can be asserted to the appropriate type
after the function call.
*/
// Parse receives anything and tries to parse it to a JSON schema-like representation
// that has the same type as the input.
//
// For example, if the input is a struct, the output will be a map with the same fields
// and nested types as the input struct.
//
// If the input is a slice or array, the output will be a slice of the same length
// containing the JSON schema-like representation of each element in the input.
//
// If the input is a map, the output will be a map with the same keys and nested types
// as the input map.
//
// If the input is a pointer to a struct, slice, or map, the output will be a pointer to
// the corresponding JSON schema-like representation.
//
// For other types (e.g. bool, string, int), the output will be the type name as a string.
//
// The function returns an interface{} value that can be asserted to the appropriate type
// after the function call.
func Parse(in interface{}) interface{} {
v := reflect.ValueOf(in)

Expand All @@ -38,7 +36,7 @@ func parse(v reflect.Value) interface{} {
switch v.Kind() {
case reflect.Struct:
if ok := isTime(v); ok {
return "DateTime"
return "date-time"
}

return parseStruct(v)
Expand All @@ -57,7 +55,7 @@ func parse(v reflect.Value) interface{} {

func parseNil(v reflect.Value) interface{} {
if ok := isTime(v); ok {
return "DateTime"
return "date-time"
}

return v.Type().String()
Expand All @@ -67,14 +65,13 @@ func parseStruct(v reflect.Value) map[string]interface{} {
m := make(map[string]interface{})

for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
structfield := v.Type().Field(i)
field := v.Type().Field(i)

if !structfield.IsExported() {
if !field.IsExported() {
continue
}

m[structfield.Name] = parse(field)
m[field.Name] = parse(v.Field(i))
}

return m
Expand All @@ -99,7 +96,6 @@ func parseMap(v reflect.Value) interface{} {

for _, key := range v.MapKeys() {
value := v.MapIndex(key)

m[key.String()] = parse(value)
}

Expand Down
20 changes: 11 additions & 9 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ type User struct {
}

type Event struct {
ID int
Title string
Date time.Time
Guests []Person
Details map[string]string
ID int
Title string
Date time.Time
Guests []Person
Details map[string]string
PtrDate *time.Time
unexported string
}

func TestParse(t *testing.T) {
Expand Down Expand Up @@ -56,15 +58,15 @@ func TestParse(t *testing.T) {
expected: `{"Age":"int","Name":"string"}`,
},
{
name: "struct with time.Time field",
name: "struct with one time.Time field filled and the other nil",
input: Event{
ID: 1,
Title: "Party",
Date: time.Now(),
Guests: []Person{{Name: "Alice", Age: 30}, {Name: "Bob", Age: 40}},
Details: map[string]string{"location": "New York", "host": "John"},
},
expected: `{"Date":"DateTime","Details": {"location": "string", "host": "string"},"Guests":"[{"Age":"int","Name":"string"}, {"Age":"int","Name":"string"}]","ID":"int","Title":"string"}`,
expected: `{"Date":"date-time","Details": {"location": "string", "host": "string"},"Guests":"[{"Age":"int","Name":"string"}, {"Age":"int","Name":"string"}]","ID":"int","Title":"string","PtrDate":"date-time"}`,
},
{
name: "slice",
Expand Down Expand Up @@ -113,11 +115,11 @@ func TestParse(t *testing.T) {

expectedMap := make(map[string]interface{})
expectedBytes, _ := json.Marshal(actual)
json.Unmarshal(expectedBytes, &expectedMap)
_ = json.Unmarshal(expectedBytes, &expectedMap)

actualMap := make(map[string]interface{})
actualBytes, _ := json.Marshal(actual)
json.Unmarshal(actualBytes, &actualMap)
_ = json.Unmarshal(actualBytes, &actualMap)

if !reflect.DeepEqual(actualMap, expectedMap) {
t.Errorf("Expected %v, but got %v", tt.expected, actual)
Expand Down

0 comments on commit f8ebee7

Please sign in to comment.