mirror of
https://github.com/ivanizag/izapple2.git
synced 2025-01-01 13:29:19 +00:00
117 lines
2.3 KiB
Go
117 lines
2.3 KiB
Go
package fujinet
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
/*
|
|
See:
|
|
https://github.com/FujiNetWIFI/fujinet-platformio/tree/master/lib/fnjson
|
|
https://github.com/FujiNetWIFI/fujinet-platformio/wiki/JSON-Query-Format
|
|
*/
|
|
|
|
type FnJson struct {
|
|
data any
|
|
Result []uint8
|
|
}
|
|
|
|
func NewFnJson() *FnJson {
|
|
var js FnJson
|
|
return &js
|
|
}
|
|
|
|
func (js *FnJson) Parse(data []uint8) ErrorCode {
|
|
// See FNJSON::parse()
|
|
err := json.Unmarshal(data, &js.data)
|
|
if err != nil {
|
|
return NetworkErrorJsonParseError
|
|
}
|
|
return NoError
|
|
}
|
|
|
|
func (js *FnJson) Query(query []uint8) {
|
|
// See FNJSON::setReadQuery
|
|
// See https://github.com/kbranigan/cJSON/blob/master/cJSON_Utils.c
|
|
if query[len(query)-1] == 0 {
|
|
query = query[0 : len(query)-1]
|
|
}
|
|
queryString := string(query)
|
|
queryString = strings.TrimSuffix(queryString, "/0")
|
|
queryString = strings.TrimPrefix(queryString, "/")
|
|
queryString = strings.TrimSuffix(queryString, "/")
|
|
path := strings.Split(queryString, "/")
|
|
|
|
js.Result = getJsonValue(nil)
|
|
current := js.data
|
|
for i := 0; i < len(path); i++ {
|
|
switch v := current.(type) {
|
|
case map[string]any:
|
|
var found bool
|
|
current, found = v[path[i]]
|
|
if !found {
|
|
// Not found
|
|
return
|
|
}
|
|
case []any:
|
|
index, err := strconv.Atoi(path[i])
|
|
if err != nil {
|
|
// Path for arrays should be an int
|
|
return
|
|
}
|
|
if index < 0 || index >= len(v) {
|
|
// Index out of bounds
|
|
return
|
|
}
|
|
current = v[index]
|
|
default:
|
|
// It's a leaf. We can't go down
|
|
return
|
|
}
|
|
}
|
|
|
|
js.Result = getJsonValue(current)
|
|
}
|
|
|
|
func getJsonValue(data any) []uint8 {
|
|
// See FNJson::getValue
|
|
if data == nil {
|
|
return []uint8("NULL")
|
|
}
|
|
|
|
switch v := data.(type) {
|
|
case bool:
|
|
if v {
|
|
return []uint8("TRUE")
|
|
} else {
|
|
return []uint8("FALSE")
|
|
}
|
|
case float64:
|
|
//if math.Floor(v) == v { // As done in FNJSON__getValue()
|
|
// It's an integer
|
|
return []uint8(strconv.Itoa(int(v)))
|
|
//} else {
|
|
// return []uint8(fmt.Sprintf("%.10f", v))
|
|
//}
|
|
case string:
|
|
return []uint8(v)
|
|
case []any:
|
|
s := make([]uint8, 0)
|
|
for i := 0; i < len(v); i++ {
|
|
s = append(s, getJsonValue(v[i])...)
|
|
}
|
|
return s
|
|
case map[string]any:
|
|
s := make([]uint8, 0)
|
|
for k, e := range v {
|
|
s = append(s, []uint8(k)...)
|
|
s = append(s, getJsonValue(e)...)
|
|
}
|
|
return s
|
|
default:
|
|
// Should not be possible for an object unmarshalled from a JSON
|
|
return []uint8("UNKNOWN")
|
|
}
|
|
}
|