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 = 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") } }