/
unquote.go
80 lines (67 loc) · 2.04 KB
/
unquote.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package jsondecimals
import (
"fmt"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"regexp"
)
//Unquote removes quotes from quoted json decimal number values in order to present them back as JSON Numbers
//
//For setting path argument please refer to https://github.com/tidwall/gjson
func Unquote(json []byte, paths ...string) ([]byte, error) {
var err error
for _, path := range paths {
result := gjson.GetBytes(json, path)
if !result.Exists() {
continue
}
switch result.Type {
case gjson.String:
json, err = unquoteValue(json, path, result)
if err != nil {
return nil, fmt.Errorf("error unquoting json decimal in path '%s' value '%s' with error: %w", path, result.Raw, err)
}
case gjson.JSON:
if !result.IsArray() {
continue
}
json, err = unquoteArray(json, path, result)
if err != nil {
return nil, fmt.Errorf("error unquoting json decimal in path '%s' array '%s' with error: %w", path, result.Raw, err)
}
default:
continue
}
}
return json, nil
}
func unquoteValue(json []byte, path string, result gjson.Result) ([]byte, error) {
numberRegex := regexp.MustCompile(`^[+\-]?(?:(?:0|[1-9]\d*)(?:\.\d*)?|\.\d+)(?:\d[eE][+\-]?\d+)?$`)
if result.Type != gjson.String || !numberRegex.MatchString(result.String()) {
return json, nil
}
return sjson.SetRawBytes(json, path, []byte(result.String()))
}
func unquoteArray(json []byte, path string, result gjson.Result) ([]byte, error) {
var err error
json, err = sjson.SetRawBytes(json, path, []byte(`[]`))
if err != nil {
return nil, err
}
result.ForEach(func(key, value gjson.Result) bool {
numberRegex := regexp.MustCompile(`^[+\-]?(?:(?:0|[1-9]\d*)(?:\.\d*)?|\.\d+)(?:\d[eE][+\-]?\d+)?$`)
if value.Type != gjson.String || !numberRegex.MatchString(value.String()) {
json, err = sjson.SetRawBytes(json, path+".-1", []byte(value.Raw))
return true
}
json, err = sjson.SetRawBytes(json, path+".-1", []byte(value.String()))
if err != nil {
return false
}
return true
})
if err != nil {
return nil, err
}
return json, nil
}