Skip to content

Commit

Permalink
Merge pull request #17 from manicar2093/fix/suppor-other-types
Browse files Browse the repository at this point in the history
fix: add handling for numbers and floats
  • Loading branch information
manicar2093 authored Jul 19, 2024
2 parents 1420626 + 97e57f6 commit 1a8d037
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 30 deletions.
75 changes: 51 additions & 24 deletions json.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,73 @@ import (
)

func (c *Optional[T]) UnmarshalJSON(data []byte) error {
var (
asString = string(data)
)
if strings.Contains(asString, "\"") {
return c.stringUnmarshall(asString)
}

return c.numberUnmarshal(asString)
}

func (c Optional[T]) MarshalJSON() ([]byte, error) {
if reflect.ValueOf(c.value).IsZero() {
return []byte("null"), nil
}
return json.Marshal(c.value)
}

func isNull(data string) bool {
return data == "null"
}

func (c *Optional[T]) stringUnmarshall(data string) error {
var (
valuer struct {
Value string `json:"value"`
}
cleanables = []struct {
find string
replacement string
}{
{find: "\n", replacement: "\\n"},
{find: "\r", replacement: "\\r"},
}
asJsonString = fmt.Sprintf(`{"value": %s}`, data)
)
asJsonString := strings.ReplaceAll(
strings.ReplaceAll(
fmt.Sprintf(`{"value": %s}`, data),
"\n",
"\\n",
),
"\r",
"\\r",
)
asJsonBytes := []byte(asJsonString)
for _, item := range cleanables {
asJsonString = strings.ReplaceAll(asJsonString, item.find, item.replacement)
}

if err := json.Unmarshal(asJsonBytes, &valuer); err != nil {
if err := json.Unmarshal([]byte(asJsonString), &valuer); err != nil {
return err
}

if valuer.Value == "null" {
if isNull(valuer.Value) {
valuer.Value = ""
}

c.isValidValue = getIsValidDataBool(valuer.Value)
if c.isValidValue {
if err := json.Unmarshal(
[]byte(strconv.Quote(valuer.Value)),
&c.value,
); err != nil {
return err
}

return c.unmarshallIntoValueIfValid([]byte(strconv.Quote(valuer.Value)))
}

func (c *Optional[T]) numberUnmarshal(data string) error {
if isNull(data) {
data = ""
}

return nil
c.isValidValue = getIsValidDataBool(data)
return c.unmarshallIntoValueIfValid([]byte(data))
}

func (c Optional[T]) MarshalJSON() ([]byte, error) {
if reflect.ValueOf(c.value).IsZero() {
return []byte("null"), nil
func (c *Optional[T]) unmarshallIntoValueIfValid(data []byte) error {
if !c.isValidValue {
return nil
}
return json.Marshal(c.value)
return json.Unmarshal(
[]byte(data),
&c.value,
)
}
42 changes: 36 additions & 6 deletions json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,47 @@ type ExampleStuct struct {
Age goption.Optional[int] `json:"age"`
}

func asJsonString(v any) string {
return fmt.Sprintf(
`"%v"`,
v,
)
}

var _ = Describe("Json", func() {

Describe("UnmarshalJSON", func() {

DescribeTable("generates optional from json string", func(expectedNameData string) {
It("generates optional from json number", func() {
var (
expectedNameData = 10000
expectedNameDataString = "10000"
jsonData = []byte(expectedNameDataString)
holder = goption.Empty[int]()
)
err := holder.UnmarshalJSON(jsonData)

Expect(err).ToNot(HaveOccurred())
Expect(holder.Get()).To(Equal(expectedNameData))
})

It("generates optional from json float", func() {
var (
expectedNameData = 100.00
expectedNameDataString = "100.00"
jsonData = []byte(expectedNameDataString)
holder = goption.Empty[float64]()
)
err := holder.UnmarshalJSON(jsonData)

Expect(err).ToNot(HaveOccurred())
Expect(holder.Get()).To(Equal(expectedNameData))
})

DescribeTable("generates optional from json string", func(expectedNameData any) {
var (
jsonData = []byte(fmt.Sprintf(
`"%v"`,
expectedNameData,
))
holder = goption.Empty[string]()
jsonData = []byte(asJsonString(expectedNameData))
holder = goption.Empty[string]()
)
err := holder.UnmarshalJSON(jsonData)

Expand Down

0 comments on commit 1a8d037

Please sign in to comment.